📄 swfdec_pattern.c
字号:
#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"/*** MORPHING ***/static voidswfdec_matrix_morph (cairo_matrix_t *dest, const cairo_matrix_t *start, const cairo_matrix_t *end, unsigned int ratio){ unsigned int inv_ratio = 65535 - ratio; g_assert (ratio < 65536); if (ratio == 0) { *dest = *start; return; } if (ratio == 65535) { *dest = *end; return; } dest->xx = (start->xx * inv_ratio + end->xx * ratio) / 65535; dest->xy = (start->xy * inv_ratio + end->xy * ratio) / 65535; dest->yy = (start->yy * inv_ratio + end->yy * ratio) / 65535; dest->yx = (start->yx * inv_ratio + end->yx * ratio) / 65535; dest->x0 = (start->x0 * inv_ratio + end->x0 * ratio) / 65535; dest->y0 = (start->y0 * inv_ratio + end->y0 * ratio) / 65535;}/*** 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);}/*** STROKE PATTERN ***/#define MAX_ALIGN 10typedef struct _SwfdecStrokePattern SwfdecStrokePattern;typedef struct _SwfdecStrokePatternClass SwfdecStrokePatternClass;#define SWFDEC_TYPE_STROKE_PATTERN (swfdec_stroke_pattern_get_type())#define SWFDEC_IS_STROKE_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_STROKE_PATTERN))#define SWFDEC_IS_STROKE_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_STROKE_PATTERN))#define SWFDEC_STROKE_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_STROKE_PATTERN, SwfdecStrokePattern))#define SWFDEC_STROKE_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_STROKE_PATTERN, SwfdecStrokePatternClass))#define SWFDEC_STROKE_PATTERN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_STROKE_PATTERN, SwfdecStrokePatternClass))struct _SwfdecStrokePattern{ SwfdecPattern pattern; guint start_width; /* width of line */ SwfdecColor start_color; /* color to paint with */ guint end_width; /* width of line */ SwfdecColor end_color; /* color to paint with */};struct _SwfdecStrokePatternClass{ SwfdecPatternClass pattern_class;};G_DEFINE_TYPE (SwfdecStrokePattern, swfdec_stroke_pattern, SWFDEC_TYPE_PATTERN);static voidswfdec_pattern_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 (); } }}static voidswfdec_stroke_pattern_paint (SwfdecPattern *pattern, cairo_t *cr, const cairo_path_t *path, const SwfdecColorTransform *trans, unsigned int ratio){ SwfdecColor color; double width; SwfdecStrokePattern *stroke = SWFDEC_STROKE_PATTERN (pattern); swfdec_pattern_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_pattern_class_init (SwfdecStrokePatternClass *klass){ SWFDEC_PATTERN_CLASS (klass)->paint = swfdec_stroke_pattern_paint;}static voidswfdec_stroke_pattern_init (SwfdecStrokePattern *pattern){}/*** 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;};G_DEFINE_TYPE (SwfdecColorPattern, swfdec_color_pattern, SWFDEC_TYPE_PATTERN);static voidswfdec_color_pattern_paint (SwfdecPattern *pat, cairo_t *cr, const cairo_path_t *path, const SwfdecColorTransform *trans, unsigned int ratio){ SwfdecColorPattern *pattern = SWFDEC_COLOR_PATTERN (pat); SwfdecColor color; cairo_append_path (cr, (cairo_path_t *) path); color = swfdec_color_apply_morph (pattern->start_color, pattern->end_color, ratio); color = swfdec_color_apply_transform (color, trans); swfdec_color_set_source (cr, color); cairo_fill (cr);}static voidswfdec_color_pattern_class_init (SwfdecColorPatternClass *klass){ SWFDEC_PATTERN_CLASS (klass)->paint = swfdec_color_pattern_paint;}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;};G_DEFINE_TYPE (SwfdecImagePattern, swfdec_image_pattern, SWFDEC_TYPE_PATTERN);static voidswfdec_image_pattern_paint (SwfdecPattern *pat, cairo_t *cr, const cairo_path_t *path, const SwfdecColorTransform *trans, unsigned int 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; cairo_append_path (cr, (cairo_path_t *) path); 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); cairo_set_source (cr, pattern); cairo_pattern_destroy (pattern); cairo_fill (cr);}static voidswfdec_image_pattern_class_init (SwfdecImagePatternClass *klass){ SWFDEC_PATTERN_CLASS (klass)->paint = swfdec_image_pattern_paint;}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 */};struct _SwfdecGradientPatternClass{ SwfdecPatternClass pattern_class;};G_DEFINE_TYPE (SwfdecGradientPattern, swfdec_gradient_pattern, SWFDEC_TYPE_PATTERN);static voidswfdec_gradient_pattern_paint (SwfdecPattern *pat, cairo_t *cr, const cairo_path_t *path, const SwfdecColorTransform *trans, unsigned int ratio){ unsigned int i; cairo_pattern_t *pattern; SwfdecColor color; double offset; SwfdecGradientPattern *gradient = SWFDEC_GRADIENT_PATTERN (pat); cairo_append_path (cr, (cairo_path_t *) path);#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 (0, 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); } } cairo_set_source (cr, pattern); cairo_pattern_destroy (pattern); cairo_fill (cr);}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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -