⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swfdec_shape.c

📁 Swfdec is a decoder/renderer for Macromedia Flash animations. The decoding and rendering engine is
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Swfdec * Copyright (C) 2003-2006 David Schleef <ds@schleef.org> *		 2005-2006 Eric Anholt <eric@anholt.net> *		 2006-2007 Benjamin Otte <otte@gnome.org> * * This library 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.1 of the License, or (at your option) any later version. *  * This library 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; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor,  * Boston, MA  02110-1301  USA */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <math.h>#include <string.h>#include "swfdec_shape.h"#include "swfdec.h"#include "swfdec_debug.h"#include "swfdec_stroke.h"G_DEFINE_TYPE (SwfdecShape, swfdec_shape, SWFDEC_TYPE_GRAPHIC)/*** PATHS ***/static voidswfdec_path_init (cairo_path_t *path){  path->status = CAIRO_STATUS_SUCCESS;  path->data = NULL;  path->num_data = 0;}static voidswfdec_path_reset (cairo_path_t *path){  path->status = CAIRO_STATUS_SUCCESS;  g_free (path->data);  path->data = NULL;  path->num_data = 0;}#define swfdec_path_require_size(path, steps) \  swfdec_path_ensure_size ((path), (path)->num_data + steps)static voidswfdec_path_ensure_size (cairo_path_t *path, int size){#define SWFDEC_PATH_STEPS 32  /* round up to next multiple of SWFDEC_PATH_STEPS */  int current_size = path->num_data - path->num_data % SWFDEC_PATH_STEPS;  if (path->num_data % SWFDEC_PATH_STEPS)    current_size += SWFDEC_PATH_STEPS;  if (size % SWFDEC_PATH_STEPS)    size += SWFDEC_PATH_STEPS - size % SWFDEC_PATH_STEPS;  g_assert (current_size % SWFDEC_PATH_STEPS == 0);  g_assert (size % SWFDEC_PATH_STEPS == 0);  while (size <= current_size)    return;  SWFDEC_LOG ("extending size of %p from %u to %u", path, current_size, size);  path->data = g_renew (cairo_path_data_t, path->data, size);}static voidswfdec_path_move_to (cairo_path_t *path, double x, double y){  cairo_path_data_t *cur;  swfdec_path_require_size (path, 2);  cur = &path->data[path->num_data++];  cur->header.type = CAIRO_PATH_MOVE_TO;  cur->header.length = 2;  cur = &path->data[path->num_data++];  cur->point.x = x;  cur->point.y = y;}static voidswfdec_path_line_to (cairo_path_t *path, double x, double y){  cairo_path_data_t *cur;  swfdec_path_require_size (path, 2);  cur = &path->data[path->num_data++];  cur->header.type = CAIRO_PATH_LINE_TO;  cur->header.length = 2;  cur = &path->data[path->num_data++];  cur->point.x = x;  cur->point.y = y;}static voidswfdec_path_curve_to (cairo_path_t *path, double start_x, double start_y,    double control_x, double control_y, double end_x, double end_y){  cairo_path_data_t *cur;  swfdec_path_require_size (path, 4);  cur = &path->data[path->num_data++];  cur->header.type = CAIRO_PATH_CURVE_TO;  cur->header.length = 4;#define WEIGHT (2.0/3.0)  cur = &path->data[path->num_data++];  cur->point.x = control_x * WEIGHT + (1-WEIGHT) * start_x;  cur->point.y = control_y * WEIGHT + (1-WEIGHT) * start_y;  cur = &path->data[path->num_data++];  cur->point.x = control_x * WEIGHT + (1-WEIGHT) * end_x;  cur->point.y = control_y * WEIGHT + (1-WEIGHT) * end_y;  cur = &path->data[path->num_data++];  cur->point.x = end_x;  cur->point.y = end_y;}static voidswfdec_path_append (cairo_path_t *path, const cairo_path_t *append){  swfdec_path_require_size (path, append->num_data);  memcpy (&path->data[path->num_data], append->data, sizeof (cairo_path_data_t) * append->num_data);  path->num_data += append->num_data;}static voidswfdec_path_append_reverse (cairo_path_t *path, const cairo_path_t *append,    double x, double y){  cairo_path_data_t *out, *in;  int i;  swfdec_path_require_size (path, append->num_data);  path->num_data += append->num_data;  out = &path->data[path->num_data - 1];  in = append->data;  for (i = 0; i < append->num_data; i++) {    switch (in[i].header.type) {      case CAIRO_PATH_LINE_TO:	out[-i].point.x = x;	out[-i].point.y = y;	out[-i - 1].header = in[i].header;	i++;	break;      case CAIRO_PATH_CURVE_TO:	out[-i].point.x = x;	out[-i].point.y = y;	out[-i - 3].header = in[i].header;	out[-i - 1].point = in[i + 1].point;	out[-i - 2].point = in[i + 2].point;	i += 3;	break;      case CAIRO_PATH_CLOSE_PATH:      case CAIRO_PATH_MOVE_TO:	/* these two don't exist in our code */      default:	g_assert_not_reached ();    }    x = in[i].point.x;    y = in[i].point.y;  }}/*** SUBPATH ***/typedef struct {  int			x_start, y_start;  int			x_end, y_end;  cairo_path_t		path;  guint			fill0style;  guint			fill1style;  guint			linestyle;  guint			max_index;} SubPath;/*** SHAPE ***/static voidswfdec_shape_vec_finish (SwfdecShapeVec * shapevec){  if (shapevec->pattern) {    g_object_unref (shapevec->pattern);    shapevec->pattern = NULL;  }  if (shapevec->fill_cr) {    cairo_destroy (shapevec->fill_cr);    shapevec->fill_cr = NULL;  }  swfdec_path_reset (&shapevec->path);}static voidswfdec_shape_vec_init (SwfdecShapeVec *vec){  swfdec_path_init (&vec->path);}static voidswfdec_shape_dispose (GObject *object){  guint i;  SwfdecShape * shape = SWFDEC_SHAPE (object);  for (i = 0; i < shape->vecs->len; i++) {    swfdec_shape_vec_finish (&g_array_index (shape->vecs, SwfdecShapeVec, i));  }  g_array_free (shape->vecs, TRUE);  for (i = 0; i < shape->fills->len; i++) {    if (g_ptr_array_index (shape->fills, i))      g_object_unref (g_ptr_array_index (shape->fills, i));  }  g_ptr_array_free (shape->fills, TRUE);  for (i = 0; i < shape->lines->len; i++) {    if (g_ptr_array_index (shape->lines, i))      g_object_unref (g_ptr_array_index (shape->lines, i));  }  g_ptr_array_free (shape->lines, TRUE);  G_OBJECT_CLASS (swfdec_shape_parent_class)->dispose (G_OBJECT (shape));}static voidswfdec_shape_render (SwfdecGraphic *graphic, cairo_t *cr,     const SwfdecColorTransform *trans, const SwfdecRect *inval, gboolean fill){  SwfdecShape *shape = SWFDEC_SHAPE (graphic);  guint i;  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);  cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);  for (i = 0; i < shape->vecs->len; i++) {    SwfdecShapeVec *vec = &g_array_index (shape->vecs, SwfdecShapeVec, i);    g_assert (vec->path.num_data);    g_assert (vec->pattern);    if (!swfdec_rect_intersect (NULL, &vec->extents, inval))      continue;        /* hack to not append paths for lines */    if (!fill && vec->last_index % 2 != 0)       continue;    if (fill) {      if (SWFDEC_IS_PATTERN (vec->pattern)) {	swfdec_pattern_paint (vec->pattern, cr, &vec->path, trans, 0);      } else {	swfdec_stroke_paint (vec->pattern, cr, &vec->path, trans, 0);      }    } else {      cairo_append_path (cr, &vec->path);    }  }}static gbooleanswfdec_shape_mouse_in (SwfdecGraphic *graphic, double x, double y){  SwfdecShapeVec *shapevec;  SwfdecShape *shape = SWFDEC_SHAPE (graphic);  static cairo_surface_t *surface = NULL;  guint i;  for (i = 0; i < shape->vecs->len; i++) {    shapevec = &g_array_index (shape->vecs, SwfdecShapeVec, i);      g_assert (shapevec->path.num_data);    g_assert (shapevec->pattern);    /* FIXME: handle strokes */    if (SWFDEC_IS_STROKE (shapevec->pattern))      continue;    if (shapevec->fill_cr == NULL) {      /* FIXME: do less memory intensive fill checking plz */      if (surface == NULL)	surface = cairo_image_surface_create (CAIRO_FORMAT_A8, 1, 1);      shapevec->fill_cr = cairo_create (surface);      cairo_set_fill_rule (shapevec->fill_cr, CAIRO_FILL_RULE_EVEN_ODD);      cairo_append_path (shapevec->fill_cr, &shapevec->path);    }    if (cairo_in_fill (shapevec->fill_cr, x, y))      return TRUE;  }  return FALSE;}static voidswfdec_shape_class_init (SwfdecShapeClass * g_class){  GObjectClass *object_class = G_OBJECT_CLASS (g_class);  SwfdecGraphicClass *graphic_class = SWFDEC_GRAPHIC_CLASS (g_class);    object_class->dispose = swfdec_shape_dispose;  graphic_class->render = swfdec_shape_render;  graphic_class->mouse_in = swfdec_shape_mouse_in;}static voidswfdec_shape_init (SwfdecShape * shape){  shape->fills = g_ptr_array_new ();  shape->lines = g_ptr_array_new ();  shape->vecs = g_array_new (FALSE, TRUE, sizeof (SwfdecShapeVec));}static voidswfdec_shape_add_styles (SwfdecSwfDecoder * s, SwfdecShape * shape,    SwfdecPatternFunc parse_fill, SwfdecStrokeFunc parse_stroke){  int n_fill_styles;  int n_line_styles;  int i;  SwfdecBits *bits = &s->b;  swfdec_bits_syncbits (bits);  shape->fills_offset = shape->fills->len;  n_fill_styles = swfdec_bits_get_u8 (bits);  if (n_fill_styles == 0xff) {    n_fill_styles = swfdec_bits_get_u16 (bits);  }  SWFDEC_LOG ("   n_fill_styles %d", n_fill_styles);  for (i = 0; i < n_fill_styles && swfdec_bits_left (bits); i++) {    SwfdecPattern *pattern;    SWFDEC_LOG ("   fill style %d:", i);    pattern = parse_fill (s);    g_ptr_array_add (shape->fills, pattern);  }  shape->lines_offset = shape->lines->len;  n_line_styles = swfdec_bits_get_u8 (bits);  if (n_line_styles == 0xff) {    n_line_styles = swfdec_bits_get_u16 (bits);  }  SWFDEC_LOG ("   n_line_styles %d", n_line_styles);  for (i = 0; i < n_line_styles && swfdec_bits_left (bits); i++) {    g_ptr_array_add (shape->lines, parse_stroke (s));  }  shape->n_fill_bits = swfdec_bits_getbits (bits, 4);  shape->n_line_bits = swfdec_bits_getbits (bits, 4);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -