📄 swfdec_pattern.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_pattern.h"#include "swfdec_bits.h"#include "swfdec_color.h"#include "swfdec_debug.h"#include "swfdec_decoder.h"#include "swfdec_image.h"#include "swfdec_stroke.h"/*** PATTERN ***/G_DEFINE_ABSTRACT_TYPE (SwfdecPattern, swfdec_pattern, G_TYPE_OBJECT);static voidswfdec_pattern_class_init (SwfdecPatternClass *klass){}static voidswfdec_pattern_init (SwfdecPattern *pattern){ cairo_matrix_init_identity (&pattern->start_transform); cairo_matrix_init_identity (&pattern->end_transform);}/*** COLOR PATTERN ***/typedef struct _SwfdecColorPattern SwfdecColorPattern;typedef struct _SwfdecColorPatternClass SwfdecColorPatternClass;#define SWFDEC_TYPE_COLOR_PATTERN (swfdec_color_pattern_get_type())#define SWFDEC_IS_COLOR_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_COLOR_PATTERN))#define SWFDEC_IS_COLOR_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_COLOR_PATTERN))#define SWFDEC_COLOR_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_COLOR_PATTERN, SwfdecColorPattern))#define SWFDEC_COLOR_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_COLOR_PATTERN, SwfdecColorPatternClass))#define SWFDEC_COLOR_PATTERN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_COLOR_PATTERN, SwfdecColorPatternClass))struct _SwfdecColorPattern{ SwfdecPattern pattern; SwfdecColor start_color; /* color to paint with at the beginning */ SwfdecColor end_color; /* color to paint with in the end */};struct _SwfdecColorPatternClass{ SwfdecPatternClass pattern_class;};GType swfdec_color_pattern_get_type (void);G_DEFINE_TYPE (SwfdecColorPattern, swfdec_color_pattern, SWFDEC_TYPE_PATTERN);static cairo_pattern_t *swfdec_color_pattern_get_pattern (SwfdecPattern *pat, const SwfdecColorTransform *trans, guint ratio){ SwfdecColorPattern *pattern = SWFDEC_COLOR_PATTERN (pat); SwfdecColor color; color = swfdec_color_apply_morph (pattern->start_color, pattern->end_color, ratio); color = swfdec_color_apply_transform (color, trans); return cairo_pattern_create_rgba ( SWFDEC_COLOR_R (color) / 255.0, SWFDEC_COLOR_G (color) / 255.0, SWFDEC_COLOR_B (color) / 255.0, SWFDEC_COLOR_A (color) / 255.0);}static voidswfdec_color_pattern_class_init (SwfdecColorPatternClass *klass){ SWFDEC_PATTERN_CLASS (klass)->get_pattern = swfdec_color_pattern_get_pattern;}static voidswfdec_color_pattern_init (SwfdecColorPattern *pattern){}/*** IMAGE PATTERN ***/typedef struct _SwfdecImagePattern SwfdecImagePattern;typedef struct _SwfdecImagePatternClass SwfdecImagePatternClass;#define SWFDEC_TYPE_IMAGE_PATTERN (swfdec_image_pattern_get_type())#define SWFDEC_IS_IMAGE_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_IMAGE_PATTERN))#define SWFDEC_IS_IMAGE_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_IMAGE_PATTERN))#define SWFDEC_IMAGE_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_IMAGE_PATTERN, SwfdecImagePattern))#define SWFDEC_IMAGE_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_IMAGE_PATTERN, SwfdecImagePatternClass))#define SWFDEC_IMAGE_PATTERN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_IMAGE_PATTERN, SwfdecImagePatternClass))struct _SwfdecImagePattern{ SwfdecPattern pattern; SwfdecImage * image; /* image to paint */ cairo_extend_t extend; cairo_filter_t filter;};struct _SwfdecImagePatternClass{ SwfdecPatternClass pattern_class;};GType swfdec_image_pattern_get_type (void);G_DEFINE_TYPE (SwfdecImagePattern, swfdec_image_pattern, SWFDEC_TYPE_PATTERN);static cairo_pattern_t *swfdec_image_pattern_get_pattern (SwfdecPattern *pat, const SwfdecColorTransform *trans, guint ratio){ SwfdecImagePattern *image = SWFDEC_IMAGE_PATTERN (pat); cairo_pattern_t *pattern; cairo_matrix_t mat; cairo_surface_t *surface; surface = swfdec_image_create_surface_transformed (image->image, trans); if (surface == NULL) return NULL; pattern = cairo_pattern_create_for_surface (surface); cairo_surface_destroy (surface); swfdec_matrix_morph (&mat, &pat->start_transform, &pat->end_transform, ratio); cairo_pattern_set_matrix (pattern, &mat); cairo_pattern_set_extend (pattern, image->extend); cairo_pattern_set_filter (pattern, image->filter); return pattern;}static voidswfdec_image_pattern_class_init (SwfdecImagePatternClass *klass){ SWFDEC_PATTERN_CLASS (klass)->get_pattern = swfdec_image_pattern_get_pattern;}static voidswfdec_image_pattern_init (SwfdecImagePattern *pattern){}/*** GRADIENT PATTERN ***/typedef struct _SwfdecGradientPattern SwfdecGradientPattern;typedef struct _SwfdecGradientPatternClass SwfdecGradientPatternClass;#define SWFDEC_TYPE_GRADIENT_PATTERN (swfdec_gradient_pattern_get_type())#define SWFDEC_IS_GRADIENT_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_GRADIENT_PATTERN))#define SWFDEC_IS_GRADIENT_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_GRADIENT_PATTERN))#define SWFDEC_GRADIENT_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_GRADIENT_PATTERN, SwfdecGradientPattern))#define SWFDEC_GRADIENT_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_GRADIENT_PATTERN, SwfdecGradientPatternClass))#define SWFDEC_GRADIENT_PATTERN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_GRADIENT_PATTERN, SwfdecGradientPatternClass))struct _SwfdecGradientPattern{ SwfdecPattern pattern; SwfdecGradient * gradient; /* gradient to paint */ gboolean radial; /* TRUE for radial gradient, FALSE for linear gradient */ gboolean morph; /* TRUE for morph gradients */ double focus; /* focus point */};struct _SwfdecGradientPatternClass{ SwfdecPatternClass pattern_class;};GType swfdec_gradient_pattern_get_type (void);G_DEFINE_TYPE (SwfdecGradientPattern, swfdec_gradient_pattern, SWFDEC_TYPE_PATTERN);static cairo_pattern_t *swfdec_gradient_pattern_get_pattern (SwfdecPattern *pat, const SwfdecColorTransform *trans, guint ratio){ guint i; cairo_pattern_t *pattern; SwfdecColor color; double offset; SwfdecGradientPattern *gradient = SWFDEC_GRADIENT_PATTERN (pat);#if 0 /* use this when https://bugs.freedesktop.org/show_bug.cgi?id=8341 is fixed */ if (gradient->radial) pattern = cairo_pattern_create_radial (0, 0, 0, 0, 0, 16384); else pattern = cairo_pattern_create_linear (-16384.0, 0, 16384.0, 0); cairo_pattern_set_matrix (pattern, &pat->transform);#else { cairo_matrix_t mat; swfdec_matrix_morph (&mat, &pat->start_transform, &pat->end_transform, ratio); if (gradient->radial) { pattern = cairo_pattern_create_radial ((16384.0 / 256.0) * gradient->focus, 0, 0, 0, 0, 16384 / 256.0); } else { pattern = cairo_pattern_create_linear (-16384.0 / 256.0, 0, 16384.0 / 256.0, 0); } cairo_matrix_scale (&mat, 1 / 256.0, 1 / 256.0); mat.x0 /= 256.0; mat.y0 /= 256.0; cairo_pattern_set_matrix (pattern, &mat); }#endif if (gradient->morph) { for (i = 0; i < gradient->gradient->n_gradients; i += 2){ color = swfdec_color_apply_morph (gradient->gradient->array[i].color, gradient->gradient->array[i + 1].color, ratio); color = swfdec_color_apply_transform (color, trans); offset = gradient->gradient->array[i].ratio * (65535 - ratio) + gradient->gradient->array[i + 1].ratio * ratio; offset /= 65535 * 255; cairo_pattern_add_color_stop_rgba (pattern, offset, SWFDEC_COLOR_R(color) / 255.0, SWFDEC_COLOR_G(color) / 255.0, SWFDEC_COLOR_B(color) / 255.0, SWFDEC_COLOR_A(color) / 255.0); } } else { for (i = 0; i < gradient->gradient->n_gradients; i++){ color = swfdec_color_apply_transform (gradient->gradient->array[i].color, trans); offset = gradient->gradient->array[i].ratio / 255.0; cairo_pattern_add_color_stop_rgba (pattern, offset, SWFDEC_COLOR_R(color) / 255.0, SWFDEC_COLOR_G(color) / 255.0, SWFDEC_COLOR_B(color) / 255.0, SWFDEC_COLOR_A(color) / 255.0); } } return pattern;}static voidswfdec_gradient_pattern_dispose (GObject *object){ SwfdecGradientPattern *gradient = SWFDEC_GRADIENT_PATTERN (object); g_free (gradient->gradient); gradient->gradient = NULL; G_OBJECT_CLASS (swfdec_gradient_pattern_parent_class)->dispose (object);}static voidswfdec_gradient_pattern_class_init (SwfdecGradientPatternClass *klass){ G_OBJECT_CLASS (klass)->dispose = swfdec_gradient_pattern_dispose; SWFDEC_PATTERN_CLASS (klass)->get_pattern = swfdec_gradient_pattern_get_pattern;}static voidswfdec_gradient_pattern_init (SwfdecGradientPattern *pattern){}/*** EXPORTED API ***/static SwfdecPattern *swfdec_pattern_do_parse (SwfdecSwfDecoder *dec, gboolean rgba){ guint paint_style_type; SwfdecBits *bits; SwfdecPattern *pattern; bits = &dec->b; paint_style_type = swfdec_bits_get_u8 (bits); SWFDEC_LOG (" type 0x%02x", paint_style_type); if (paint_style_type == 0x00) { pattern = g_object_new (SWFDEC_TYPE_COLOR_PATTERN, NULL); if (rgba) { SWFDEC_COLOR_PATTERN (pattern)->start_color = swfdec_bits_get_rgba (bits); } else { SWFDEC_COLOR_PATTERN (pattern)->start_color = swfdec_bits_get_color (bits); } SWFDEC_COLOR_PATTERN (pattern)->end_color = SWFDEC_COLOR_PATTERN (pattern)->start_color; SWFDEC_LOG (" color %08x", SWFDEC_COLOR_PATTERN (pattern)->start_color); } else if (paint_style_type == 0x10 || paint_style_type == 0x12 || paint_style_type == 0x13) { SwfdecGradientPattern *gradient; pattern = g_object_new (SWFDEC_TYPE_GRADIENT_PATTERN, NULL); gradient = SWFDEC_GRADIENT_PATTERN (pattern); swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL); pattern->end_transform = pattern->start_transform; if (rgba) { gradient->gradient = swfdec_bits_get_gradient_rgba (bits); } else { gradient->gradient = swfdec_bits_get_gradient (bits); } gradient->radial = (paint_style_type != 0x10); /* FIXME: need a way to ensure 0x13 only happens in Flash 8 */ if (paint_style_type == 0x13) { gradient->focus = swfdec_bits_get_s16 (bits) / 256.0; } } else if (paint_style_type >= 0x40 && paint_style_type <= 0x43) { guint paint_id = swfdec_bits_get_u16 (bits); SWFDEC_LOG (" background paint id = %d (type 0x%02x)", paint_id, paint_style_type); if (paint_id == 65535) { /* FIXME: someone explain this magic paint id here */ pattern = g_object_new (SWFDEC_TYPE_COLOR_PATTERN, NULL); SWFDEC_COLOR_PATTERN (pattern)->start_color = SWFDEC_COLOR_COMBINE (0, 255, 255, 255); SWFDEC_COLOR_PATTERN (pattern)->end_color = SWFDEC_COLOR_PATTERN (pattern)->start_color; swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL); pattern->end_transform = pattern->start_transform; } else { pattern = g_object_new (SWFDEC_TYPE_IMAGE_PATTERN, NULL); swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL); pattern->end_transform = pattern->start_transform; SWFDEC_IMAGE_PATTERN (pattern)->image = swfdec_swf_decoder_get_character (dec, paint_id); if (!SWFDEC_IS_IMAGE (SWFDEC_IMAGE_PATTERN (pattern)->image)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -