📄 render2d.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / 2D rendering module * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include "render2d.h"#include "stacks2d.h"#include "visualsurface2d.h"#include <gpac/options.h>#ifndef GPAC_DISABLE_SVG#include "svg_stacks.h"#endifvoid R2D_MapCoordsToAR(Render2D *sr, s32 *x, s32 *y){ if (sr->surface->center_coords) { /*revert to BIFS like*/ *x = *x - sr->compositor->width /2; *y = sr->compositor->height/2 - *y; } else { *x -= sr->offset_x; *y -= sr->offset_y; } /*if no size info scaling is never applied*/ if (!sr->compositor->has_size_info) return; if (!sr->scalable_zoom) { Fixed _x, _y; _x = INT2FIX(*x); _y = INT2FIX(*y); _x = gf_muldiv(_x, INT2FIX(sr->compositor->scene_width ), INT2FIX(sr->compositor->width)); _y = gf_muldiv(_y, INT2FIX(sr->compositor->scene_height), INT2FIX(sr->compositor->height)); *x = FIX2INT(_x); *y = FIX2INT(_y); }}static void R2D_SetUserTransform(Render2D *sr, Fixed zoom, Fixed tx, Fixed ty, Bool is_resize) { Fixed ratio; Fixed old_tx, old_ty, old_z; gf_sr_lock(sr->compositor, 1); old_tx = tx; old_ty = ty; old_z = sr->zoom; if (zoom <= 0) zoom = FIX_ONE/1000; sr->trans_x = tx; sr->trans_y = ty; if (zoom != sr->zoom) { ratio = gf_divfix(zoom, sr->zoom); sr->trans_x = gf_mulfix(sr->trans_x, ratio); sr->trans_y = gf_mulfix(sr->trans_y, ratio); sr->zoom = zoom; /*recenter surface*/ if (!sr->surface->center_coords) { Fixed c_x, c_y, nc_x, nc_y; c_x = INT2FIX(sr->compositor->width/2); nc_y = c_y = INT2FIX(sr->compositor->height/2); nc_x = gf_mulfix(c_x, ratio); nc_y = gf_mulfix(c_y, ratio); sr->trans_x -= (nc_x-c_x); sr->trans_y -= (nc_y-c_y); } } gf_mx2d_init(sr->top_effect->transform); gf_mx2d_add_scale(&sr->top_effect->transform, gf_mulfix(sr->zoom,sr->scale_x), gf_mulfix(sr->zoom,sr->scale_y));// gf_mx2d_add_scale(&sr->top_effect->transform, sr->zoom, sr->zoom); gf_mx2d_add_translation(&sr->top_effect->transform, sr->trans_x, sr->trans_y); if (sr->rotation) gf_mx2d_add_rotation(&sr->top_effect->transform, 0, 0, sr->rotation); if (!sr->surface->center_coords) { gf_mx2d_add_translation(&sr->top_effect->transform, INT2FIX(sr->offset_x), INT2FIX(sr->offset_y)); } GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 2D] Changing Zoom (%g) and Pan (%g %g)\n", FIX2FLT(sr->zoom), FIX2FLT(sr->trans_x) , FIX2FLT(sr->trans_y))); sr->compositor->draw_next_frame = 1; sr->top_effect->invalidate_all = 1;#ifndef GPAC_DISABLE_SVG if (sr->use_dom_events) { GF_DOM_Event evt; memset(&evt, 0, sizeof(GF_DOM_Event)); evt.prev_scale = sr->scale_x*old_z; evt.new_scale = sr->scale_x*sr->zoom; if (is_resize) { evt.type = GF_EVENT_RESIZE; } else if (evt.prev_scale == evt.new_scale) { /*cannot get params for scroll events*/ evt.type = GF_EVENT_SCROLL; } else { evt.screen_rect.x = INT2FIX(sr->offset_x); evt.screen_rect.y = INT2FIX(sr->offset_y); evt.screen_rect.width = INT2FIX(sr->cur_width); evt.screen_rect.height = INT2FIX(sr->cur_height); evt.prev_translate.x = old_tx; evt.prev_translate.y = old_ty; evt.new_translate.x = sr->trans_x; evt.new_translate.y = sr->trans_y; evt.type = GF_EVENT_ZOOM; } gf_dom_event_fire(gf_sg_get_root_node(sr->compositor->scene), NULL, &evt); }#endif gf_sr_lock(sr->compositor, 0);}void R2D_SetScaling(Render2D *sr, Fixed scaleX, Fixed scaleY){ sr->scale_x = scaleX; sr->scale_y = scaleY; R2D_SetUserTransform(sr, sr->zoom, sr->trans_x, sr->trans_y, 1);}void R2D_ResetSurfaces(Render2D *sr){ VisualSurface2D *surf; u32 i=0; while ((surf = (VisualSurface2D *)gf_list_enum(sr->surfaces_2D, &i))) { /*reset display list*/ surf->cur_context = surf->context; if (surf->cur_context) surf->cur_context->drawable = NULL; while (surf->prev_nodes) { struct _drawable_store *cur = surf->prev_nodes; surf->prev_nodes = cur->next; free(cur); } surf->last_prev_entry = NULL; surf->to_redraw.count = 0; }}void R2D_SceneReset(GF_VisualRenderer *vr){ u32 flag; Render2D *sr = (Render2D*) vr->user_priv; if (!sr) return; R2D_ResetSurfaces(sr); while (gf_list_count(sr->sensors)) { gf_list_rem(sr->sensors, 0); } flag = sr->top_effect->trav_flags; effect_reset(sr->top_effect); sr->top_effect->trav_flags = flag; sr->compositor->reset_graphics = 1; sr->trans_x = sr->trans_y = 0; sr->zoom = FIX_ONE; sr->grab_node = NULL; sr->grab_ctx = NULL; sr->grab_use = NULL; sr->focus_node = NULL; R2D_SetScaling(sr, sr->scale_x, sr->scale_y); /*force resetup of main surface in case we're switching coord system*/ sr->main_surface_setup = 0; sr->navigation_disabled = 0; VS2D_ResetGraphics(sr->surface);}GF_Rect R2D_ClipperToPixelMetrics(RenderEffect2D *eff, SFVec2f size){ GF_Rect res; if (eff->surface->composite) { res.width = INT2FIX(eff->surface->width); res.height = INT2FIX(eff->surface->height); } else { res.width = INT2FIX(eff->surface->render->compositor->scene_width); res.height = INT2FIX(eff->surface->render->compositor->scene_height); } if (eff->is_pixel_metrics) { if (size.x>=0) res.width = size.x; if (size.y>=0) res.height = size.y; } else { if (size.x>=0) res.width = gf_mulfix(res.width, size.x / 2); if (size.y>=0) res.height = gf_mulfix(res.height, size.y / 2); } res = gf_rect_center(res.width, res.height); return res;}void R2D_RegisterSurface(Render2D *sr, struct _visual_surface_2D *surf){ if (R2D_IsSurfaceRegistered(sr, surf)) return; gf_list_add(sr->surfaces_2D, surf);}void R2D_UnregisterSurface(Render2D *sr, struct _visual_surface_2D *surf){ gf_list_del_item(sr->surfaces_2D, surf);}Bool R2D_IsSurfaceRegistered(Render2D *sr, struct _visual_surface_2D *surf){ VisualSurface2D *tmp; u32 i = 0; while ((tmp = (VisualSurface2D *)gf_list_enum(sr->surfaces_2D, &i))) { if (tmp == surf) return 1; } return 0;}void effect_add_sensor(RenderEffect2D *eff, SensorHandler *ptr, GF_Matrix2D *mat){ SensorContext *ctx; if (!ptr) return; ctx = (SensorContext *)malloc(sizeof(SensorContext)); ctx->h_node = ptr; if (mat) { gf_mx2d_copy(ctx->matrix, *mat); } else { gf_mx2d_init(ctx->matrix); } gf_list_add(eff->sensors, ctx);}void effect_pop_sensor(RenderEffect2D *eff){ SensorContext *ctx; u32 last = gf_list_count(eff->sensors); if (!last) return; ctx = (SensorContext *)gf_list_get(eff->sensors, last-1); gf_list_rem(eff->sensors, last-1); free(ctx);}void effect_reset_sensors(RenderEffect2D *eff){ SensorContext *ctx; while (gf_list_count(eff->sensors)) { ctx = (SensorContext *)gf_list_get(eff->sensors, 0); gf_list_rem(eff->sensors, 0); free(ctx); }}void effect_reset(RenderEffect2D *eff){ GF_List *bck = eff->sensors; memset(eff, 0, sizeof(RenderEffect2D)); eff->sensors = bck; if (bck) effect_reset_sensors(eff); gf_mx2d_init(eff->transform); gf_cmx_init(&eff->color_mat);}void effect_delete(RenderEffect2D *eff){ if (eff->sensors) { effect_reset_sensors(eff); gf_list_del(eff->sensors); } free(eff);}Bool is_sensor_node(GF_Node *node){ switch (gf_node_get_tag(node)) { case TAG_MPEG4_TouchSensor: case TAG_MPEG4_PlaneSensor2D: case TAG_MPEG4_DiscSensor: case TAG_MPEG4_ProximitySensor2D: return 1; /*anchor is not considered as a child sensor node when picking sensors*/ /*case TAG_MPEG4_Anchor:*/#ifndef GPAC_DISABLE_SVG /*case TAG_SVG_a: */#endif default: return 0; }}SensorHandler *get_sensor_handler(GF_Node *n){ SensorHandler *hs; switch (gf_node_get_tag(n)) { case TAG_MPEG4_Anchor: hs = r2d_anchor_get_handler(n); break; case TAG_MPEG4_DiscSensor: hs = r2d_ds_get_handler(n); break; case TAG_MPEG4_TouchSensor: hs = r2d_touch_sensor_get_handler(n); break; case TAG_MPEG4_PlaneSensor2D: hs = r2d_ps2D_get_handler(n); break; case TAG_MPEG4_ProximitySensor2D: hs = r2d_prox2D_get_handler(n); break; default: return NULL; } if (hs && hs->IsEnabled(hs)) return hs; return NULL;}void R2D_RegisterSensor(GF_Renderer *compositor, SensorHandler *sh){ SensorHandler *tmp; u32 i=0; Render2D *sr = (Render2D *)compositor->visual_renderer->user_priv; while ((tmp = (SensorHandler *)gf_list_enum(sr->sensors, &i))) { if (tmp == sh) return; } gf_list_add(sr->sensors, sh);}void R2D_UnregisterSensor(GF_Renderer *compositor, SensorHandler *sh){ Render2D *sr = (Render2D *)compositor->visual_renderer->user_priv; gf_list_del_item(sr->sensors, sh);}#define R2DSETCURSOR(t) { GF_Event evt; evt.type = GF_EVENT_SET_CURSOR; evt.cursor.cursor_type = (t); sr->compositor->video_out->ProcessEvent(sr->compositor->video_out, &evt); }#ifndef GPAC_DISABLE_SVGBool R2D_ExecuteDOMEvent(GF_VisualRenderer *vr, GF_Event *event, Fixed X, Fixed Y){ GF_DOM_Event evt; u32 cursor_type; Bool ret = 0; Render2D *sr = (Render2D *)vr->user_priv; cursor_type = GF_CURSOR_NORMAL; /*all mouse events*/ if (event->type<=GF_EVENT_MOUSEMOVE) { DrawableContext *ctx = VS2D_PickContext(sr->surface, X, Y); if (ctx) { cursor_type = sr->last_sensor; memset(&evt, 0, sizeof(GF_DOM_Event)); evt.clientX = evt.screenX = FIX2INT(X); evt.clientY = evt.screenY = FIX2INT(Y); evt.bubbles = 1; evt.cancelable = 1; evt.key_flags = sr->compositor->key_states; switch (event->type) { case GF_EVENT_MOUSEMOVE: evt.cancelable = 0; if ((sr->grab_node != ctx->drawable) || (sr->grab_use != ctx->appear) ) { /*mouse out*/ if (sr->grab_node) { evt.relatedTarget = ctx->drawable->node; evt.type = GF_EVENT_MOUSEOUT; ret += gf_dom_event_fire(sr->grab_node->node, sr->grab_use, &evt); /*prepare mouseOver*/ evt.relatedTarget = sr->grab_node->node; } /*mouse over*/ evt.type = GF_EVENT_MOUSEOVER; ret += gf_dom_event_fire(ctx->drawable->node, ctx->appear, &evt); sr->grab_ctx = ctx; sr->grab_node = ctx->drawable; sr->grab_use = ctx->appear; } else { evt.type = GF_EVENT_MOUSEMOVE; ret += gf_dom_event_fire(ctx->drawable->node, ctx->appear, &evt); } break; case GF_EVENT_MOUSEDOWN: if ((sr->last_click_x!=evt.screenX) || (sr->last_click_y!=evt.screenY)) sr->num_clicks = 0; evt.type = GF_EVENT_MOUSEDOWN; evt.detail = event->mouse.button; ret += gf_dom_event_fire(ctx->drawable->node, ctx->appear, &evt); sr->last_click_x = evt.screenX; sr->last_click_y = evt.screenY; break; case GF_EVENT_MOUSEUP: evt.type = GF_EVENT_MOUSEUP; evt.detail = event->mouse.button; ret += gf_dom_event_fire(ctx->drawable->node, ctx->appear, &evt); if ((sr->last_click_x==evt.screenX) || (sr->last_click_y==evt.screenY)) { sr->num_clicks ++; evt.type = GF_EVENT_CLICK; evt.detail = sr->num_clicks; ret += gf_dom_event_fire(ctx->drawable->node, ctx->appear, &evt); } break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -