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

📄 swfdec_shape.c

📁 Swfdec is a decoder/renderer for Macromedia Flash animations. The decoding and rendering engine is
💻 C
📖 第 1 页 / 共 3 页
字号:
inttag_define_shape (SwfdecSwfDecoder * s, guint tag){  SwfdecBits *bits = &s->b;  SwfdecShape *shape;  int id;  id = swfdec_bits_get_u16 (bits);  shape = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_SHAPE);  if (!shape)    return SWFDEC_STATUS_OK;  SWFDEC_INFO ("id=%d", id);  swfdec_bits_get_rect (bits, &SWFDEC_GRAPHIC (shape)->extents);  swfdec_shape_add_styles (s, shape, swfdec_pattern_parse, swfdec_stroke_parse);  swfdec_shape_get_recs (s, shape, swfdec_pattern_parse, swfdec_stroke_parse);  return SWFDEC_STATUS_OK;}inttag_define_shape_3 (SwfdecSwfDecoder * s, guint tag){  SwfdecBits *bits = &s->b;  SwfdecShape *shape;  int id;  id = swfdec_bits_get_u16 (bits);  shape = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_SHAPE);  if (!shape)    return SWFDEC_STATUS_OK;  swfdec_bits_get_rect (bits, &SWFDEC_GRAPHIC (shape)->extents);  swfdec_shape_add_styles (s, shape, swfdec_pattern_parse_rgba, swfdec_stroke_parse_rgba);  swfdec_shape_get_recs (s, shape, swfdec_pattern_parse_rgba, swfdec_stroke_parse_rgba);  return SWFDEC_STATUS_OK;}inttag_define_shape_4 (SwfdecSwfDecoder *s, guint tag){  SwfdecBits *bits = &s->b;  SwfdecShape *shape;  int id;  SwfdecRect tmp;  gboolean has_scale_strokes, has_noscale_strokes;  id = swfdec_bits_get_u16 (bits);  shape = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_SHAPE);  if (!shape)    return SWFDEC_STATUS_OK;  swfdec_bits_get_rect (bits, &SWFDEC_GRAPHIC (shape)->extents);  SWFDEC_LOG ("  extents: %g %g x %g %g",       SWFDEC_GRAPHIC (shape)->extents.x0, SWFDEC_GRAPHIC (shape)->extents.y0,      SWFDEC_GRAPHIC (shape)->extents.x1, SWFDEC_GRAPHIC (shape)->extents.y1);  swfdec_bits_get_rect (bits, &tmp);  SWFDEC_LOG ("  extents: %g %g x %g %g",       tmp.x0, tmp.y0, tmp.x1, tmp.y1);  swfdec_bits_getbits (bits, 6);  has_scale_strokes = swfdec_bits_getbit (bits);  has_noscale_strokes = swfdec_bits_getbit (bits);  SWFDEC_LOG ("  has scaling strokes: %d", has_scale_strokes);  SWFDEC_LOG ("  has non-scaling strokes: %d", has_noscale_strokes);  swfdec_shape_add_styles (s, shape, swfdec_pattern_parse_rgba, swfdec_stroke_parse_extended);  swfdec_shape_get_recs (s, shape, swfdec_pattern_parse_rgba, swfdec_stroke_parse_extended);  return SWFDEC_STATUS_OK;}/* The shape creation process is a bit complicated since it requires matching  * the Flash model to the cairo model. Note that this code is just random  * guessing and nothing substantial. Otherwise I'd have a testsuite. :) * It does the following steps: * - Accumulate all sub path into an array of SubPath structs. a sub path is  *   the path between 2 style change records. * - For every fill style used, accumulate all paths in order of appearance.  *   The code assumes that every fill path is closed. * - Collect the lines. * - Sort the array so that lines get drawn after their left and right fill,  *   but as early as possible. SubPath.max_index and ShapeVec.last_index are  *   used for this. *//* FIXME: It might be that the Flash code uses a different order, namely  * drawing all fills followed by all lines per style record. So everything after * new styles appeared is drawn later. * The current code works though, so I'm not interested in testing that idea ;) */static GSList *swfdec_shape_accumulate_one_polygon (SwfdecShape *shape, SwfdecShapeVec *target,    guint style, SubPath *paths, guint start, guint paths_len, guint *max){  guint i;  GSList *found = NULL;  int x, y;  g_assert (style != 0);  /* paths[start] is our starting point */  if (paths[start].fill0style == style) {    paths[start].fill0style = 0;  } else {    g_assert (style == paths[start].fill1style);    paths[start].fill1style = 0;  }  x = paths[start].x_end;  y = paths[start].y_end;  found = g_slist_prepend (found, &paths[start]);  *max = start;  swfdec_path_move_to (&target->path, paths[start].x_start, paths[start].y_start);  swfdec_path_append (&target->path, &paths[start].path);  while (x != paths[start].x_start || y != paths[start].y_start) {    SWFDEC_LOG ("now looking for point %u %u", x, y);    for (i = start; i < paths_len; i++) {      if (paths[i].fill0style != style && paths[i].fill1style != style)	continue;      if (paths[i].x_start == x && paths[i].y_start == y) {	SWFDEC_LOG ("  found it %u", i);	x = paths[i].x_end;	y = paths[i].y_end;	swfdec_path_append (&target->path, &paths[i].path);      } else if (paths[i].x_end == x && paths[i].y_end == y) {	SWFDEC_LOG ("  found it reverse %u", i);	x = paths[i].x_start;	y = paths[i].y_start;	swfdec_path_append_reverse (&target->path, &paths[i].path, x, y);      } else {	continue;      }      if (paths[i].fill0style == style)	paths[i].fill0style = 0;      else	paths[i].fill1style = 0;      found = g_slist_prepend (found, &paths[i]);      *max = i;      break;    }    if (i == paths_len) {      SWFDEC_ERROR ("could not find a closed path for style %u, starting at %d %d", style,	  paths[start].x_start, paths[start].y_start);      goto fail;    }  }  return found;fail:  g_slist_free (found);  return NULL;}static voidswfdec_shape_accumulate_one_fill (SwfdecShape *shape, SubPath *paths,     guint start, guint paths_len){  SwfdecShapeVec *target;  guint i, style, max = 0, cur;  GSList *walk, *found = NULL;  g_array_set_size (shape->vecs, shape->vecs->len + 1);  target = &g_array_index (shape->vecs, SwfdecShapeVec, shape->vecs->len - 1);  swfdec_shape_vec_init (target);  if (paths[start].fill0style != 0)    style = paths[start].fill0style;  else    style = paths[start].fill1style;  for (i = start; i < paths_len; i++) {    if (paths[i].fill0style == style) {      walk = swfdec_shape_accumulate_one_polygon (shape, target, style, 	  paths, i, paths_len, &cur);      if (walk) {	found = g_slist_concat (found, walk);	max = MAX (max, cur);      } else {	goto fail;      }    }    if (paths[i].fill1style == style) {      walk = swfdec_shape_accumulate_one_polygon (shape, target, style, 	  paths, i, paths_len, &cur);      if (walk) {	found = g_slist_concat (found, walk);	max = MAX (max, cur);      } else {	goto fail;      }    }  }  target->last_index = 2 * max;  for (walk = found; walk; walk = walk->next) {    SubPath *sub = walk->data;    sub->max_index = MAX (sub->max_index, max);  }  if (style > shape->fills->len) {    SWFDEC_ERROR ("style index %u is too big, only %u styles available", style,	shape->fills->len);    goto fail;  } else {    target->pattern = g_ptr_array_index (shape->fills, style - 1);    if (target->pattern == NULL)      goto fail;    g_object_ref (target->pattern);  }  g_slist_free (found);  return;fail:  g_slist_free (found);  swfdec_shape_vec_finish (target);  g_array_set_size (shape->vecs, shape->vecs->len - 1);}static voidswfdec_shape_accumulate_fills (SwfdecShape *shape, SubPath *paths, guint paths_len){  guint i;  for (i = 0; i < paths_len; i++) {    if (paths[i].fill0style != 0)      swfdec_shape_accumulate_one_fill (shape, paths, i, paths_len);    if (paths[i].fill1style != 0)      swfdec_shape_accumulate_one_fill (shape, paths, i, paths_len);  }}static voidswfdec_shape_accumulate_lines (SwfdecShape *shape, SubPath *paths, guint paths_len){  SwfdecShapeVec target = { 0, };  guint i;  for (i = 0; i < paths_len; i++) {    if (paths[i].linestyle == 0)      continue;    if (paths[i].linestyle > shape->lines->len) {      SWFDEC_ERROR ("linestyle index %u is too big, only %u styles available",	  paths[i].linestyle, shape->lines->len);      continue;    }    swfdec_shape_vec_init (&target);    swfdec_path_move_to (&target.path, paths[i].x_start, paths[i].y_start);    swfdec_path_append (&target.path, &paths[i].path);    target.pattern = g_ptr_array_index (shape->lines, paths[i].linestyle - 1);    g_object_ref (target.pattern);    target.last_index = 2 * paths[i].max_index + 1;    g_array_append_val (shape->vecs, target);  }}static intswfdec_shape_vec_compare (gconstpointer a, gconstpointer b){  return ((const SwfdecShapeVec *) a)->last_index - ((const SwfdecShapeVec *) b)->last_index;}typedef enum {  SWFDEC_SHAPE_TYPE_END,  SWFDEC_SHAPE_TYPE_CHANGE,  SWFDEC_SHAPE_TYPE_LINE,  SWFDEC_SHAPE_TYPE_CURVE} SwfdecShapeType;static SwfdecShapeTypeswfdec_shape_peek_type (SwfdecBits *bits){  guint ret = swfdec_bits_peekbits (bits, 6);  if (ret == 0)    return SWFDEC_SHAPE_TYPE_END;  if ((ret & 0x20) == 0)    return SWFDEC_SHAPE_TYPE_CHANGE;  if ((ret & 0x10) == 0)    return SWFDEC_SHAPE_TYPE_CURVE;  return SWFDEC_SHAPE_TYPE_LINE;}static voidswfdec_shape_parse_curve (SwfdecBits *bits, SubPath *path,    int *x, int *y){  int n_bits;  int cur_x, cur_y;  int control_x, control_y;  if (swfdec_bits_getbits (bits, 2) != 2) {    g_assert_not_reached ();  }  n_bits = swfdec_bits_getbits (bits, 4) + 2;  cur_x = *x;  cur_y = *y;  control_x = cur_x + swfdec_bits_getsbits (bits, n_bits);  control_y = cur_y + swfdec_bits_getsbits (bits, n_bits);  SWFDEC_LOG ("   control %d,%d", control_x, control_y);  *x = control_x + swfdec_bits_getsbits (bits, n_bits);  *y = control_y + swfdec_bits_getsbits (bits, n_bits);  SWFDEC_LOG ("   anchor %d,%d", *x, *y);  if (path) {    swfdec_path_curve_to (&path->path, 	cur_x, cur_y,	control_x, control_y, 	*x, *y);  } else {    SWFDEC_ERROR ("no path to curve in");  }}static voidswfdec_shape_parse_line (SwfdecBits *bits, SubPath *path,    int *x, int *y, gboolean add_as_curve){  int n_bits;  int general_line_flag;  int cur_x, cur_y;  if (swfdec_bits_getbits (bits, 2) != 3) {    g_assert_not_reached ();  }  cur_x = *x;  cur_y = *y;  n_bits = swfdec_bits_getbits (bits, 4) + 2;  general_line_flag = swfdec_bits_getbit (bits);  if (general_line_flag == 1) {    *x += swfdec_bits_getsbits (bits, n_bits);    *y += swfdec_bits_getsbits (bits, n_bits);  } else {    int vert_line_flag = swfdec_bits_getbit (bits);    if (vert_line_flag == 0) {      *x += swfdec_bits_getsbits (bits, n_bits);    } else {      *y += swfdec_bits_getsbits (bits, n_bits);    }  }  SWFDEC_LOG ("   line to %d,%d", *x, *y);  if (path) {    if (add_as_curve)      swfdec_path_curve_to (&path->path, cur_x, cur_y,	  (cur_x + *x) / 2, (cur_y + *y) / 2, *x, *y);

⌨️ 快捷键说明

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