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

📄 swfdec_stroke.c

📁 Swfdec is a decoder/renderer for Macromedia Flash animations. The decoding and rendering engine is
💻 C
字号:
/* Swfdec * Copyright (C) 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 "swfdec_stroke.h"#include "swfdec_bits.h"#include "swfdec_color.h"#include "swfdec_debug.h"#include "swfdec_decoder.h"#include "swfdec_image.h"#define MAX_ALIGN 10G_DEFINE_TYPE (SwfdecStroke, swfdec_stroke, G_TYPE_OBJECT);static voidswfdec_stroke_append_path_snapped (cairo_t *cr, const cairo_path_t *path){  cairo_path_data_t *data;  double x, y;  int i;  data = path->data;  for (i = 0; i < path->num_data; i++) {    switch (data[i].header.type) {      case CAIRO_PATH_MOVE_TO:	i++;	x = data[i].point.x;	y = data[i].point.y;	cairo_user_to_device (cr, &x, &y);	x = rint (x - 0.5) + 0.5;	y = rint (y - 0.5) + 0.5;	cairo_device_to_user (cr, &x, &y);	/* FIXME: currently we need to clamp this due to extents */	x = CLAMP (x, data[i].point.x - MAX_ALIGN, data[i].point.x + MAX_ALIGN);	y = CLAMP (y, data[i].point.y - MAX_ALIGN, data[i].point.y + MAX_ALIGN);	cairo_move_to (cr, x, y);	break;      case CAIRO_PATH_LINE_TO:	i++;	x = data[i].point.x;	y = data[i].point.y;	cairo_user_to_device (cr, &x, &y);	x = rint (x - 0.5) + 0.5;	y = rint (y - 0.5) + 0.5;	cairo_device_to_user (cr, &x, &y);	/* FIXME: currently we need to clamp this due to extents */	x = CLAMP (x, data[i].point.x - MAX_ALIGN, data[i].point.x + MAX_ALIGN);	y = CLAMP (y, data[i].point.y - MAX_ALIGN, data[i].point.y + MAX_ALIGN);	cairo_line_to (cr, x, y);	break;      case CAIRO_PATH_CURVE_TO:	x = data[i+3].point.x;	y = data[i+3].point.y;	cairo_user_to_device (cr, &x, &y);	x = rint (x - 0.5) + 0.5;	y = rint (y - 0.5) + 0.5;	cairo_device_to_user (cr, &x, &y);	/* FIXME: currently we need to clamp this due to extents */	x = CLAMP (x, data[i+3].point.x - MAX_ALIGN, data[i+3].point.x + MAX_ALIGN);	y = CLAMP (y, data[i+3].point.y - MAX_ALIGN, data[i+3].point.y + MAX_ALIGN);	cairo_curve_to (cr, data[i+1].point.x, data[i+1].point.y, 	    data[i+2].point.x, data[i+2].point.y, x, y);	i += 3;	break;      case CAIRO_PATH_CLOSE_PATH:	/* doesn't exist in our code */      default:	g_assert_not_reached ();    }  }}voidswfdec_stroke_paint (SwfdecStroke *stroke, cairo_t *cr, const cairo_path_t *path,    const SwfdecColorTransform *trans, guint ratio){  SwfdecColor color;  double width;  g_return_if_fail (SWFDEC_IS_STROKE (stroke));  g_return_if_fail (cr != NULL);  g_return_if_fail (path != NULL);  g_return_if_fail (trans != NULL);  g_return_if_fail (ratio < 65536);  cairo_set_line_cap (cr, stroke->start_cap);  cairo_set_line_join (cr, stroke->join);  if (stroke->join == CAIRO_LINE_JOIN_MITER)    cairo_set_miter_limit (cr, stroke->miter_limit);  swfdec_stroke_append_path_snapped (cr, path);  color = swfdec_color_apply_morph (stroke->start_color, stroke->end_color, ratio);  color = swfdec_color_apply_transform (color, trans);  swfdec_color_set_source (cr, color);  if (ratio == 0) {    width = stroke->start_width;  } else if (ratio == 65535) {    width = stroke->end_width;  } else {    width = (stroke->start_width * (65535 - ratio) + stroke->end_width * ratio) / 65535;  }  if (width < SWFDEC_TWIPS_SCALE_FACTOR)    width = SWFDEC_TWIPS_SCALE_FACTOR;  cairo_set_line_width (cr, width);  cairo_stroke (cr);}static voidswfdec_stroke_class_init (SwfdecStrokeClass *klass){}static voidswfdec_stroke_init (SwfdecStroke *stroke){  stroke->start_cap = CAIRO_LINE_CAP_ROUND;  stroke->end_cap = CAIRO_LINE_CAP_ROUND;  stroke->join = CAIRO_LINE_JOIN_ROUND;}/*** EXPORTED API ***/SwfdecStroke *swfdec_stroke_parse (SwfdecSwfDecoder *dec){  SwfdecBits *bits = &dec->b;  SwfdecStroke *stroke = g_object_new (SWFDEC_TYPE_STROKE, NULL);  stroke->start_width = swfdec_bits_get_u16 (bits);  stroke->end_width = stroke->start_width;  stroke->start_color = swfdec_bits_get_color (bits);  stroke->end_color = stroke->start_color;  SWFDEC_LOG ("new stroke: width %u color %08x", stroke->start_width, stroke->start_color);  return stroke;}SwfdecStroke *swfdec_stroke_parse_rgba (SwfdecSwfDecoder *dec){  SwfdecBits *bits = &dec->b;  SwfdecStroke *stroke = g_object_new (SWFDEC_TYPE_STROKE, NULL);  stroke->start_width = swfdec_bits_get_u16 (bits);  stroke->end_width = stroke->start_width;  stroke->start_color = swfdec_bits_get_rgba (bits);  stroke->end_color = stroke->start_color;  SWFDEC_LOG ("new stroke: width %u color %08x", stroke->start_width, stroke->start_color);  return stroke;}SwfdecStroke *swfdec_stroke_parse_morph (SwfdecSwfDecoder *dec){  SwfdecBits *bits = &dec->b;  SwfdecStroke *stroke = g_object_new (SWFDEC_TYPE_STROKE, NULL);  stroke->start_width = swfdec_bits_get_u16 (bits);  stroke->end_width = swfdec_bits_get_u16 (bits);  stroke->start_color = swfdec_bits_get_rgba (bits);  stroke->end_color = swfdec_bits_get_rgba (bits);  SWFDEC_LOG ("new stroke: width %u => %u color %08X => %08X",       stroke->start_width, stroke->end_width,      stroke->start_color, stroke->end_color);  return stroke;}SwfdecStroke *swfdec_stroke_new (guint width, SwfdecColor color){  SwfdecStroke *stroke = g_object_new (SWFDEC_TYPE_STROKE, NULL);  stroke->start_width = width;  stroke->end_width = width;  stroke->start_color = color;  stroke->end_color = color;  return stroke;}static cairo_line_cap_tswfdec_line_cap_get (guint cap){  switch (cap) {    case 0:      return CAIRO_LINE_CAP_ROUND;    case 1:      return CAIRO_LINE_CAP_BUTT;    case 2:      return CAIRO_LINE_CAP_SQUARE;    default:      SWFDEC_ERROR ("invalid line cap value %u", cap);      return CAIRO_LINE_CAP_ROUND;  }}static cairo_line_join_tswfdec_line_join_get (guint join){  switch (join) {    case 0:      return CAIRO_LINE_JOIN_ROUND;    case 1:      return CAIRO_LINE_JOIN_BEVEL;    case 2:      return CAIRO_LINE_JOIN_MITER;    default:      SWFDEC_ERROR ("invalid line join value %u", join);      return CAIRO_LINE_JOIN_ROUND;  }}static SwfdecStroke *swfdec_stroke_do_parse_extended (SwfdecSwfDecoder *dec, gboolean morph){  SwfdecBits *bits = &dec->b;  guint tmp;  gboolean has_pattern;  SwfdecStroke *stroke = g_object_new (SWFDEC_TYPE_STROKE, NULL);  stroke->start_width = swfdec_bits_get_u16 (bits);  if (morph) {    stroke->end_width = swfdec_bits_get_u16 (bits);    SWFDEC_LOG ("  width: %u => %u", stroke->start_width, stroke->end_width);  } else {    stroke->end_width = stroke->start_width;    SWFDEC_LOG ("  width: %u", stroke->start_width);  }  tmp = swfdec_bits_getbits (bits, 2);  SWFDEC_LOG ("  start cap: %u", tmp);  stroke->start_cap = swfdec_line_cap_get (tmp);  tmp = swfdec_bits_getbits (bits, 2);  SWFDEC_LOG ("  line join: %u", tmp);  stroke->join = swfdec_line_join_get (tmp);  has_pattern = swfdec_bits_getbit (bits);  SWFDEC_LOG ("  has pattern: %d", has_pattern);  stroke->no_hscale = swfdec_bits_getbit (bits);  SWFDEC_LOG ("  no hscale: %d", stroke->no_hscale);  stroke->no_vscale = swfdec_bits_getbit (bits);  SWFDEC_LOG ("  no vscale: %d", stroke->no_vscale);  stroke->align_pixel = swfdec_bits_getbit (bits);  SWFDEC_LOG ("  align pixels: %d", stroke->align_pixel);  tmp = swfdec_bits_getbits (bits, 5);  stroke->no_close = swfdec_bits_getbit (bits);  SWFDEC_LOG ("  no close: %d", stroke->no_close);  tmp = swfdec_bits_getbits (bits, 2);  SWFDEC_LOG ("  end cap: %u", tmp);  stroke->end_cap = swfdec_line_cap_get (tmp);  if (stroke->end_cap != stroke->start_cap) {    SWFDEC_WARNING ("FIXME: different caps on start and end of line are unsupported");  }  if (stroke->join == CAIRO_LINE_JOIN_MITER) {    stroke->miter_limit = swfdec_bits_get_u16 (bits);    SWFDEC_LOG ("  miter limit: %u", stroke->miter_limit);  }  if (has_pattern) {    if (morph) {      stroke->pattern = swfdec_pattern_parse_morph (dec);    } else {      stroke->pattern = swfdec_pattern_parse_rgba (dec);    }  } else {    stroke->start_color = swfdec_bits_get_rgba (bits);    if (morph) {      stroke->end_color = swfdec_bits_get_rgba (bits);      SWFDEC_LOG ("  color: #%08X", stroke->start_color);    } else {      stroke->end_color = stroke->start_color;      SWFDEC_LOG ("  color: #%08X", stroke->start_color);    }  }  return stroke;}SwfdecStroke *swfdec_stroke_parse_extended (SwfdecSwfDecoder *dec){  g_return_val_if_fail (SWFDEC_IS_SWF_DECODER (dec), NULL);  return swfdec_stroke_do_parse_extended (dec, FALSE);}SwfdecStroke *swfdec_stroke_parse_morph_extended (SwfdecSwfDecoder *dec){  g_return_val_if_fail (SWFDEC_IS_SWF_DECODER (dec), NULL);  return swfdec_stroke_do_parse_extended (dec, TRUE);}

⌨️ 快捷键说明

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