📄 swfdec_pattern.c
字号:
g_object_unref (pattern); SWFDEC_ERROR ("could not find image with id %u for pattern", paint_id); return NULL; } if (paint_style_type == 0x40 || paint_style_type == 0x42) { SWFDEC_IMAGE_PATTERN (pattern)->extend = CAIRO_EXTEND_REPEAT; } else {#if 0 /* not implemented yet in cairo */ SWFDEC_IMAGE_PATTERN (pattern)->extend = CAIRO_EXTEND_PAD;#else SWFDEC_IMAGE_PATTERN (pattern)->extend = CAIRO_EXTEND_NONE;#endif } if (paint_style_type == 0x40 || paint_style_type == 0x41) { SWFDEC_IMAGE_PATTERN (pattern)->filter = CAIRO_FILTER_BILINEAR; } else { SWFDEC_IMAGE_PATTERN (pattern)->filter = CAIRO_FILTER_NEAREST; } } } else { SWFDEC_ERROR ("unknown paint style type 0x%02x", paint_style_type); return NULL; } if (cairo_matrix_invert (&pattern->start_transform)) { SWFDEC_ERROR ("paint transform matrix not invertible, resetting"); cairo_matrix_init_identity (&pattern->start_transform); cairo_matrix_init_identity (&pattern->end_transform); } swfdec_bits_syncbits (bits); return pattern;}/** * swfdec_pattern_parse: * @dec: a #SwfdecDecoder to parse from * @rgba: TRUE if colors are RGBA, FALSE if they're just RGB * * Continues parsing @dec into a new #SwfdecPattern * * Returns: a new #SwfdecPattern or NULL on error **/SwfdecPattern *swfdec_pattern_parse (SwfdecSwfDecoder *dec){ g_return_val_if_fail (dec != NULL, NULL); return swfdec_pattern_do_parse (dec, FALSE);}SwfdecPattern *swfdec_pattern_parse_rgba (SwfdecSwfDecoder *dec){ g_return_val_if_fail (dec != NULL, NULL); return swfdec_pattern_do_parse (dec, TRUE);}/** * swfdec_pattern_parse_morph: * @dec: a #SwfdecDecoder to parse from * * Continues parsing @dec into a new #SwfdecPattern. This function is used by * morph shapes. * * Returns: a new #SwfdecPattern or NULL on error **/SwfdecPattern *swfdec_pattern_parse_morph (SwfdecSwfDecoder *dec){ guint paint_style_type; SwfdecBits *bits; SwfdecPattern *pattern; g_return_val_if_fail (dec != NULL, NULL); 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); SWFDEC_COLOR_PATTERN (pattern)->start_color = swfdec_bits_get_rgba (bits); SWFDEC_COLOR_PATTERN (pattern)->end_color = swfdec_bits_get_rgba (bits); SWFDEC_LOG (" color %08x => %08x", SWFDEC_COLOR_PATTERN (pattern)->start_color, SWFDEC_COLOR_PATTERN (pattern)->end_color); } else if (paint_style_type == 0x10 || paint_style_type == 0x12) { pattern = g_object_new (SWFDEC_TYPE_GRADIENT_PATTERN, NULL); swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL); swfdec_bits_get_matrix (bits, &pattern->end_transform, NULL); SWFDEC_GRADIENT_PATTERN (pattern)->gradient = swfdec_bits_get_morph_gradient (bits); SWFDEC_GRADIENT_PATTERN (pattern)->radial = (paint_style_type == 0x12); SWFDEC_GRADIENT_PATTERN (pattern)->morph = TRUE; } 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); swfdec_bits_get_matrix (bits, &pattern->end_transform, NULL); } else { pattern = g_object_new (SWFDEC_TYPE_IMAGE_PATTERN, NULL); swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL); swfdec_bits_get_matrix (bits, &pattern->end_transform, NULL); SWFDEC_IMAGE_PATTERN (pattern)->image = swfdec_swf_decoder_get_character (dec, paint_id); if (!SWFDEC_IS_IMAGE (SWFDEC_IMAGE_PATTERN (pattern)->image)) { g_object_unref (pattern); SWFDEC_ERROR ("could not find image with id %u for pattern", paint_id); return NULL; } if (paint_style_type == 0x40 || paint_style_type == 0x42) { SWFDEC_IMAGE_PATTERN (pattern)->extend = CAIRO_EXTEND_REPEAT; } else { SWFDEC_IMAGE_PATTERN (pattern)->extend = CAIRO_EXTEND_NONE; } if (paint_style_type == 0x40 || paint_style_type == 0x41) { SWFDEC_IMAGE_PATTERN (pattern)->filter = CAIRO_FILTER_BILINEAR; } else { SWFDEC_IMAGE_PATTERN (pattern)->filter = CAIRO_FILTER_NEAREST; } } } else { SWFDEC_ERROR ("unknown paint style type 0x%02x", paint_style_type); return NULL; } if (cairo_matrix_invert (&pattern->start_transform)) { SWFDEC_ERROR ("paint start transform matrix not invertible, resetting"); cairo_matrix_init_identity (&pattern->start_transform); } if (cairo_matrix_invert (&pattern->end_transform)) { SWFDEC_ERROR ("paint end transform matrix not invertible, resetting"); cairo_matrix_init_identity (&pattern->end_transform); } swfdec_bits_syncbits (bits); return pattern;}/** * swfdec_pattern_paint: * @pattern: a #SwfdecPattern * @cr: the context to paint * @path: the path to paint * @trans: color transformation to apply before painting * @ratio: For morphshapes, the ratio to apply. Other objects should set this to 0. * * Fills the current path of @cr with the given @pattern. **/voidswfdec_pattern_paint (SwfdecPattern *pattern, cairo_t *cr, const cairo_path_t *path, const SwfdecColorTransform *trans, guint ratio){ cairo_pattern_t *cpattern; g_return_if_fail (SWFDEC_IS_PATTERN (pattern)); g_return_if_fail (cr != NULL); g_return_if_fail (path != NULL); g_return_if_fail (trans != NULL); g_return_if_fail (ratio < 65536); cpattern = swfdec_pattern_get_pattern (pattern, trans, ratio); if (cpattern == NULL) return;#if CAIRO_VERSION_MAJOR < 2 && CAIRO_VERSION_MINOR < 4 cairo_append_path (cr, (cairo_path_t *) path);#else cairo_append_path (cr, path);#endif cairo_set_source (cr, cpattern); cairo_pattern_destroy (cpattern); cairo_fill (cr);}/** * swfdec_pattern_new_color: * @color: color to paint in * * Creates a new pattern to paint with the given color * * Returns: a new @SwfdecPattern to paint with */SwfdecPattern * swfdec_pattern_new_color (SwfdecColor color){ SwfdecPattern *pattern = g_object_new (SWFDEC_TYPE_COLOR_PATTERN, NULL); SWFDEC_COLOR_PATTERN (pattern)->start_color = color; SWFDEC_COLOR_PATTERN (pattern)->end_color = color; return pattern;}char *swfdec_pattern_to_string (SwfdecPattern *pattern){ g_return_val_if_fail (SWFDEC_IS_PATTERN (pattern), NULL); if (SWFDEC_IS_IMAGE_PATTERN (pattern)) { SwfdecImagePattern *image = SWFDEC_IMAGE_PATTERN (pattern); if (image->image->width == 0) cairo_surface_destroy (swfdec_image_create_surface (image->image)); return g_strdup_printf ("%ux%u image %u (%s, %s)", image->image->width, image->image->height, SWFDEC_CHARACTER (image->image)->id, image->extend == CAIRO_EXTEND_REPEAT ? "repeat" : "no repeat", image->filter == CAIRO_FILTER_BILINEAR ? "bilinear" : "nearest"); } else if (SWFDEC_IS_COLOR_PATTERN (pattern)) { if (SWFDEC_COLOR_PATTERN (pattern)->start_color == SWFDEC_COLOR_PATTERN (pattern)->end_color) return g_strdup_printf ("color #%08X", SWFDEC_COLOR_PATTERN (pattern)->start_color); else return g_strdup_printf ("color #%08X => #%08X", SWFDEC_COLOR_PATTERN (pattern)->start_color, SWFDEC_COLOR_PATTERN (pattern)->end_color); } else if (SWFDEC_IS_GRADIENT_PATTERN (pattern)) { SwfdecGradientPattern *gradient = SWFDEC_GRADIENT_PATTERN (pattern); return g_strdup_printf ("%s gradient (%u colors)", gradient->radial ? "radial" : "linear", gradient->gradient->n_gradients); } else { return g_strdup_printf ("%s", G_OBJECT_TYPE_NAME (pattern)); }}static voidswfdec_path_get_extents (const cairo_path_t *path, SwfdecRect *extents, double line_width){ cairo_path_data_t *data = path->data; int i; double x = 0, y = 0; gboolean need_current = TRUE; gboolean start = TRUE;#define ADD_POINT(rect, x, y) G_STMT_START{ \ if (rect->x0 > x + line_width) \ rect->x0 = x + line_width; \ if (rect->x1 < x - line_width) \ rect->x1 = x - line_width; \ if (rect->y0 > y + line_width) \ rect->y0 = y + line_width; \ if (rect->y1 < y - line_width) \ rect->y1 = y - line_width; \}G_STMT_END g_assert (line_width >= 0.0); for (i = 0; i < path->num_data; i++) { switch (data[i].header.type) { case CAIRO_PATH_CURVE_TO: if (need_current) { if (start) { start = FALSE; extents->x0 = x - line_width; extents->x1 = x + line_width; extents->y0 = y - line_width; extents->y1 = y + line_width; } else { ADD_POINT (extents, x, y); } need_current = FALSE; } ADD_POINT (extents, data[i+1].point.x, data[i+1].point.y); ADD_POINT (extents, data[i+2].point.x, data[i+2].point.y); ADD_POINT (extents, data[i+3].point.x, data[i+3].point.y); i += 3; break; case CAIRO_PATH_LINE_TO: if (need_current) { if (start) { start = FALSE; extents->x0 = x - line_width; extents->x1 = x + line_width; extents->y0 = y - line_width; extents->y1 = y + line_width; } else { ADD_POINT (extents, x, y); } need_current = FALSE; } ADD_POINT (extents, data[i+1].point.x, data[i+1].point.y); i++; break; case CAIRO_PATH_CLOSE_PATH: x = 0; y = 0; break; case CAIRO_PATH_MOVE_TO: x = data[i+1].point.x; y = data[i+1].point.y; i++; break; default: g_assert_not_reached (); } }#undef ADD_POINT}#define MAX_ALIGN 10voidswfdec_pattern_get_path_extents (SwfdecPattern *pattern, const cairo_path_t *path, SwfdecRect *extents){ if (SWFDEC_IS_STROKE (pattern)) { SwfdecStroke *stroke = SWFDEC_STROKE (pattern); double line_width = MAX (stroke->start_width, stroke->end_width); line_width = MAX (line_width, SWFDEC_TWIPS_SCALE_FACTOR); swfdec_path_get_extents (path, extents, line_width / 2); /* add offsets for pixel-alignment here */ extents->x0 -= MAX_ALIGN; extents->y0 -= MAX_ALIGN; extents->x1 += MAX_ALIGN; extents->y1 += MAX_ALIGN; } else { swfdec_path_get_extents (path, extents, 0.0); }}cairo_pattern_t *swfdec_pattern_get_pattern (SwfdecPattern *pattern, const SwfdecColorTransform *trans, guint ratio){ SwfdecPatternClass *klass; g_return_val_if_fail (SWFDEC_IS_PATTERN (pattern), NULL); g_return_val_if_fail (trans != NULL, NULL); g_return_val_if_fail (ratio < 65536, NULL); klass = SWFDEC_PATTERN_GET_CLASS (pattern); g_assert (klass->get_pattern); return klass->get_pattern (pattern, trans, ratio);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -