gboolean swfdec_amf_parse_one (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAmfType expected_type, SwfdecAsValue *rval) { SwfdecAmfParseFunc func; guint type; g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), 0); g_return_val_if_fail (context->global != NULL, 0); g_return_val_if_fail (bits != NULL, FALSE); g_return_val_if_fail (rval != NULL, FALSE); g_return_val_if_fail (expected_type < SWFDEC_AMF_N_TYPES, FALSE); type = swfdec_bits_get_u8 (bits); if (type != expected_type) { SWFDEC_ERROR ("parse object should be type %u, but is %u", expected_type, type); return FALSE; } if (type >= SWFDEC_AMF_N_TYPES || (func = parse_funcs[type]) == NULL) { SWFDEC_ERROR ("no parse func for AMF type %u", type); return FALSE; } return func (context, bits, rval); }
void swfdec_as_function_init_context (SwfdecAsContext *context) { SwfdecAsObject *function, *proto; SwfdecAsValue val; g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context)); function = SWFDEC_AS_OBJECT (swfdec_as_object_add_function (context->global, SWFDEC_AS_STR_Function, NULL)); swfdec_as_object_set_variable_flags (context->global, SWFDEC_AS_STR_Function, SWFDEC_AS_VARIABLE_VERSION_6_UP); context->Function = function; SWFDEC_AS_VALUE_SET_OBJECT (&val, function); swfdec_as_object_set_variable_and_flags (function, SWFDEC_AS_STR_constructor, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT); proto = swfdec_as_object_new_empty (context); context->Function_prototype = proto; SWFDEC_AS_VALUE_SET_OBJECT (&val, proto); swfdec_as_object_set_variable_and_flags (function, SWFDEC_AS_STR_prototype, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT); swfdec_as_object_set_variable_and_flags (function, SWFDEC_AS_STR___proto__, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT | SWFDEC_AS_VARIABLE_VERSION_6_UP); SWFDEC_AS_VALUE_SET_OBJECT (&val, function); swfdec_as_object_set_variable_and_flags (proto, SWFDEC_AS_STR_constructor, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT); }
SwfdecColorTransformAs * swfdec_color_transform_as_new_from_transform (SwfdecAsContext *context, const SwfdecColorTransform *transform) { SwfdecColorTransformAs *transform_as; SwfdecAsObject *object; g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL); g_return_val_if_fail (transform != NULL, NULL); transform_as = g_object_new (SWFDEC_TYPE_COLOR_TRANSFORM_AS, "context", context, NULL); /* do it this way so the constructor isn't called */ object = swfdec_as_object_new (context, NULL); swfdec_as_object_set_relay (object, SWFDEC_AS_RELAY (transform_as)); swfdec_as_object_set_constructor_by_name (object, SWFDEC_AS_STR_flash, SWFDEC_AS_STR_geom, SWFDEC_AS_STR_ColorTransform, NULL); transform_as->ra = transform->ra / 256.0; transform_as->ga = transform->ga / 256.0; transform_as->ba = transform->ba / 256.0; transform_as->aa = transform->aa / 256.0; transform_as->rb = transform->rb; transform_as->gb = transform->gb; transform_as->bb = transform->bb; transform_as->ab = transform->ab; return transform_as; }
/** * swfdec_as_native_function_new: * @context: a #SwfdecAsContext * @name: name of the function * @native: function to call when executed * @prototype: The object to be used as "prototype" property for the created * function or %NULL for none. * * Creates a new native function, that will execute @native when called. You * might want to use swfdec_as_object_add_function() instead of this function. * * Returns: a new #SwfdecAsFunction **/ SwfdecAsFunction * swfdec_as_native_function_new (SwfdecAsContext *context, const char *name, SwfdecAsNative native, SwfdecAsObject *prototype) { SwfdecAsNativeFunction *fun; g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL); g_return_val_if_fail (native != NULL, NULL); g_return_val_if_fail (prototype == NULL || SWFDEC_IS_AS_OBJECT (prototype), NULL); fun = g_object_new (SWFDEC_TYPE_AS_NATIVE_FUNCTION, "context", context, NULL); fun->native = native; fun->name = g_strdup (name); /* need to set prototype before setting the constructor or Function.constructor * being CONSTANT disallows setting it. */ if (prototype) { SwfdecAsValue val; SWFDEC_AS_VALUE_SET_OBJECT (&val, prototype); swfdec_as_object_set_variable_and_flags (SWFDEC_AS_OBJECT (fun), SWFDEC_AS_STR_prototype, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT); } swfdec_as_function_set_constructor (SWFDEC_AS_FUNCTION (fun)); return SWFDEC_AS_FUNCTION (fun); }
static void swfdec_print_job_init_properties (SwfdecAsContext *cx) { SwfdecAsValue val; SwfdecAsObject *xml, *proto; // FIXME: We should only initialize if the prototype Object has not been // initialized by any object's constructor with native properties // (TextField, TextFormat, XML, XMLNode at least) g_return_if_fail (SWFDEC_IS_AS_CONTEXT (cx)); swfdec_as_object_get_variable (cx->global, SWFDEC_AS_STR_PrintJob, &val); if (!SWFDEC_AS_VALUE_IS_OBJECT (val)) return; xml = SWFDEC_AS_VALUE_GET_OBJECT (val); swfdec_as_object_get_variable (xml, SWFDEC_AS_STR_prototype, &val); if (!SWFDEC_AS_VALUE_IS_OBJECT (val)) return; proto = SWFDEC_AS_VALUE_GET_OBJECT (val); swfdec_as_object_add_native_variable (proto, SWFDEC_AS_STR_orientation, swfdec_print_job_get_orientation, NULL); swfdec_as_object_add_native_variable (proto, SWFDEC_AS_STR_pageHeight, swfdec_print_job_get_pageHeight, NULL); swfdec_as_object_add_native_variable (proto, SWFDEC_AS_STR_pageWidth, swfdec_print_job_get_pageWidth, NULL); swfdec_as_object_add_native_variable (proto, SWFDEC_AS_STR_paperHeight, swfdec_print_job_get_paperHeight, NULL); swfdec_as_object_add_native_variable (proto, SWFDEC_AS_STR_paperWidth, swfdec_print_job_get_paperWidth, NULL); }
// inner function for swfdec_as_array_sort_compare static int swfdec_as_array_sort_compare_values (SwfdecAsContext *cx, const SwfdecAsValue *a, const SwfdecAsValue *b, SortOption options, SwfdecAsFunction *custom_function) { int retval; g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (cx), 0); g_return_val_if_fail (SWFDEC_IS_AS_VALUE (a), 0); g_return_val_if_fail (SWFDEC_IS_AS_VALUE (b), 0); g_return_val_if_fail (custom_function == NULL || SWFDEC_IS_AS_FUNCTION (custom_function), 0); if (custom_function != NULL) { SwfdecAsValue argv[2] = { *a, *b }; SwfdecAsValue ret; SwfdecAsContext *context = swfdec_gc_object_get_context (custom_function); swfdec_as_function_call (custom_function, NULL, 2, argv, &ret); retval = swfdec_as_value_to_integer (context, &ret); } else if (options & SORT_OPTION_NUMERIC && (SWFDEC_AS_VALUE_IS_NUMBER (a) || SWFDEC_AS_VALUE_IS_NUMBER (b)) && !SWFDEC_AS_VALUE_IS_UNDEFINED (a) && !SWFDEC_AS_VALUE_IS_UNDEFINED (b)) { if (!SWFDEC_AS_VALUE_IS_NUMBER (a)) { retval = 1; } else if (!SWFDEC_AS_VALUE_IS_NUMBER (b)) { retval = -1; } else { double an = swfdec_as_value_to_number (cx, a); double bn = swfdec_as_value_to_number (cx, b); retval = (an < bn ? -1 : (an > bn ? 1 : 0)); } } else { // can't pass swfdec_as_value_to_string calls directly to compare // functions, since the order of these is important const char *a_str = swfdec_as_value_to_string (cx, a); const char *b_str = swfdec_as_value_to_string (cx, b); if (options & SORT_OPTION_CASEINSENSITIVE) { retval = g_strcasecmp (a_str, b_str); } else { retval = strcmp (a_str, b_str); } } if (options & SORT_OPTION_DESCENDING) retval = -retval; return retval; }
static int swfdec_as_array_sort_compare (gconstpointer a_ptr, gconstpointer b_ptr, gpointer user_data) { const SwfdecAsValue *a = &((SortEntry *)a_ptr)->value; const SwfdecAsValue *b = &((SortEntry *)b_ptr)->value; SortCompareData *data = user_data; int retval; g_return_val_if_fail (SWFDEC_IS_AS_VALUE (a), 0); g_return_val_if_fail (SWFDEC_IS_AS_VALUE (b), 0); g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (data->context), 0); g_return_val_if_fail (data->options != NULL, 0); g_return_val_if_fail (data->custom_function == NULL || SWFDEC_IS_AS_FUNCTION (data->custom_function), 0); g_return_val_if_fail (data->fields == NULL || data->fields[0] != NULL, 0); if (data->fields == NULL) { retval = swfdec_as_array_sort_compare_values (data->context, a, b, data->options[0], data->custom_function); } else { SwfdecAsValue a_comp, b_comp; SwfdecAsObject *object; int i; i = 0; do { object = swfdec_as_value_to_object (data->context, a); if (object) { swfdec_as_object_get_variable (object, data->fields[i], &a_comp); } else { SWFDEC_AS_VALUE_SET_UNDEFINED (&a_comp); } object = swfdec_as_value_to_object (data->context, b); if (object) { swfdec_as_object_get_variable (object, data->fields[i], &b_comp); } else { SWFDEC_AS_VALUE_SET_UNDEFINED (&b_comp); } retval = swfdec_as_array_sort_compare_values (data->context, &a_comp, &b_comp, data->options[i], data->custom_function); } while (retval == 0 && data->fields[++i] != NULL); } if (retval == 0) data->equal_found = TRUE; return retval; }
/** * swfdec_as_array_new: * @context: a #SwfdecAsContext * * Creates a new #SwfdecAsArray. * * Returns: the new array **/ SwfdecAsObject * swfdec_as_array_new (SwfdecAsContext *context) { SwfdecAsObject *ret; g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL); ret = g_object_new (SWFDEC_TYPE_AS_ARRAY, "context", context, NULL); swfdec_as_object_set_constructor_by_name (ret, SWFDEC_AS_STR_Array, NULL); swfdec_as_array_set_length_object (ret, 0); return ret; }
/** * swfdec_as_native_function_check: * @cx: a #SwfdecAsContext * @object: this object passed to the native function * @type: expected type of @object or 0 for any * @result: pointer to variable taking cast result of @object * @argc: count of arguments passed to the function * @argv: arguments passed to the function * @args: argument conversion string * @...: pointers to variables taking converted arguments * * This function is a convenience function to validate and convert arguments to * a native function while avoiding common pitfalls. You typically want to call * it at the beginning of every native function you write. Or you can use the * SWFDEC_AS_CHECK() macro instead which calls this function. * The @cx, @object, @argc and @argv paramters should be passed verbatim from * the function call to your native function. If @type is not 0, @object is then * checked to be of that type and cast to @result. After that the @args string * is used to convert the arguments. Every character in @args describes the * conversion of one argument. For that argument, you have to pass a pointer * that takes the value. For the conversion, the default conversion functions * like swfdec_as_value_to_string() are used. If not enough arguments are * available, the function stops converting and returns %NULL. The following * conversion characters are allowed:<itemizedlist> * <listitem><para>"b": convert to boolean. Requires a %gboolean pointer * </para></listitem> * <listitem><para>"i": convert to integer. Requires an %integer pointer * </para></listitem> * <listitem><para>"m": convert to an existing movieclip. This is only valid * inside Swfdec. Requires a %SwfdecMovie pointer. * </para></listitem> * <listitem><para>"M": convert to a movieclip or %NULL. This is only valid * inside Swfdec. If the movie has already been destroyed, * the pointer will be set to %NULL</para></listitem> * <listitem><para>"n": convert to number. Requires a %double pointer * </para></listitem> * <listitem><para>"o": convert to object. Requires a #SwfdecAsObject pointer. * If the conversion fails, this function immediately returns * %FALSE.</para></listitem> * <listitem><para>"O": convert to object or %NULL. Requires a #SwfdecAsObject * pointer.</para></listitem> * <listitem><para>"s": convert to garbage-collected string. Requires a const * %char pointer</para></listitem> * <listitem><para>"v": copy the value. The given argument must be a pointer * to a #SwfdecAsValue</para></listitem> * <listitem><para>"|": optional arguments follow. Optional arguments will be * initialized to the empty value for their type. This * conversion character is only allowed once in the conversion * string.</para></listitem> * </itemizedlist> * * Returns: %TRUE if the conversion succeeded, %FALSE otherwise **/ gboolean swfdec_as_native_function_check (SwfdecAsContext *cx, SwfdecAsObject *object, GType type, gpointer *result, guint argc, SwfdecAsValue *argv, const char *args, ...) { gboolean ret; va_list varargs; g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (cx), FALSE); g_return_val_if_fail (type == 0 || result != NULL, FALSE); va_start (varargs, args); ret = swfdec_as_native_function_checkv (cx, object, type, result, argc, argv, args, varargs); va_end (varargs); return ret; }
/** * swfdec_as_native_function_new: * @context: a #SwfdecAsContext * @name: name of the function * @native: function to call when executed * * Creates a new native function, that will execute @native when called. You * might want to use swfdec_as_object_add_function() instead of this function. * * Returns: a new #SwfdecAsFunction **/ SwfdecAsFunction * swfdec_as_native_function_new (SwfdecAsContext *context, const char *name, SwfdecAsNative native) { SwfdecAsFunction *fun; SwfdecAsObject *object; g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL); g_return_val_if_fail (native != NULL, NULL); fun = swfdec_as_native_function_new_bare (context, name, native); object = swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (fun)); swfdec_as_object_set_constructor_by_name (object, SWFDEC_AS_STR_Function, NULL); swfdec_as_object_set_variable_flags (object, SWFDEC_AS_STR___proto__, SWFDEC_AS_VARIABLE_VERSION_6_UP); return fun; }
SwfdecAsFunction * swfdec_as_native_function_new_bare (SwfdecAsContext *context, const char *name, SwfdecAsNative native) { SwfdecAsNativeFunction *fun; SwfdecAsObject *object; g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL); g_return_val_if_fail (native != NULL, NULL); fun = g_object_new (SWFDEC_TYPE_AS_NATIVE_FUNCTION, "context", context, NULL); fun->native = native; fun->name = g_strdup (name); object = swfdec_as_object_new_empty (context); swfdec_as_object_set_relay (object, SWFDEC_AS_RELAY (fun)); return SWFDEC_AS_FUNCTION (fun); }
guint swfdec_amf_parse (SwfdecAsContext *context, SwfdecBits *bits, guint n_items, ...) { va_list args; guint i; g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), 0); g_return_val_if_fail (context->global != NULL, 0); g_return_val_if_fail (bits != NULL, 0); va_start (args, n_items); for (i = 0; i < n_items; i++) { SwfdecAmfType type = va_arg (args, SwfdecAmfType); SwfdecAsValue *val = va_arg (args, SwfdecAsValue *); if (!swfdec_amf_parse_one (context, bits, type, val)) break; } va_end (args); return i; }
SwfdecBitmapData * swfdec_bitmap_data_new (SwfdecAsContext *context, gboolean transparent, guint width, guint height) { SwfdecBitmapData *bitmap; g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL); g_return_val_if_fail (width > 0, NULL); g_return_val_if_fail (height > 0, NULL); if (!swfdec_as_context_try_use_mem (context, width * height * 4)) return NULL; bitmap = g_object_new (SWFDEC_TYPE_BITMAP_DATA, "context", context, NULL); bitmap->surface = cairo_image_surface_create ( transparent ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, width, height); swfdec_as_object_set_constructor_by_name (SWFDEC_AS_OBJECT (bitmap), SWFDEC_AS_STR_flash, SWFDEC_AS_STR_display, SWFDEC_AS_STR_BitmapData, NULL); return bitmap; }
/** * swfdec_as_native_function_checkv: * @cx: a #SwfdecAsContext * @object: this object passed to the native function * @type: expected type of @object * @result: pointer to variable taking cast result of @object * @argc: count of arguments passed to the function * @argv: arguments passed to the function * @args: argument conversion string * @varargs: pointers to variables taking converted arguments * * This is the valist version of swfdec_as_native_function_check(). See that * function for details. * * Returns: %TRUE if the conversion succeeded, %FALSE otherwise **/ gboolean swfdec_as_native_function_checkv (SwfdecAsContext *cx, SwfdecAsObject *object, GType type, gpointer *result, guint argc, SwfdecAsValue *argv, const char *args, va_list varargs) { guint i; gboolean optional = FALSE; g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (cx), FALSE); g_return_val_if_fail (type == 0 || result != NULL, FALSE); /* check that we got a valid type */ if (type) { if (G_TYPE_CHECK_INSTANCE_TYPE (object, type)) { *result = object; } else if (object && G_TYPE_CHECK_INSTANCE_TYPE (object->relay, type)) { *result = object->relay; } else { return FALSE; } } for (i = 0; *args && i < argc; i++, args++) { switch (*args) { case 'v': { SwfdecAsValue *val = va_arg (varargs, SwfdecAsValue *); *val = argv[i]; } break; case 'b': { gboolean *b = va_arg (varargs, gboolean *); *b = swfdec_as_value_to_boolean (cx, argv[i]); } break; case 'i': { int *j = va_arg (varargs, int *); *j = swfdec_as_value_to_integer (cx, argv[i]); } break; case 'm': case 'M': { SwfdecMovie *m; SwfdecMovie **arg = va_arg (varargs, SwfdecMovie **); if (SWFDEC_AS_VALUE_IS_MOVIE (argv[i])) { m = SWFDEC_AS_VALUE_GET_MOVIE (argv[i]); } else { m = NULL; } if (m == NULL && *args != 'M') return FALSE; *arg = m; } break; case 'n': { double *d = va_arg (varargs, double *); *d = swfdec_as_value_to_number (cx, argv[i]); } break; case 's': { const char **s = va_arg (varargs, const char **); *s = swfdec_as_value_to_string (cx, argv[i]); } break; case 'o': case 'O': { SwfdecAsObject **o = va_arg (varargs, SwfdecAsObject **); *o = swfdec_as_value_to_object (cx, argv[i]); if (*o == NULL && *args != 'O') return FALSE; } break; case '|': g_return_val_if_fail (optional == FALSE, FALSE); optional = TRUE; i--; break; default: g_warning ("'%c' is not a valid type conversion", *args); return FALSE; } } if (*args && !optional && *args != '|') return FALSE; return TRUE; }
static void swfdec_as_array_do_sort (SwfdecAsContext *cx, SwfdecAsObject *object, const SortOption *options, SwfdecAsFunction *custom_function, const char **fields, SwfdecAsValue *ret) { SortEntry *array; SortCollectData collect_data; SortCompareData compare_data; gint32 i, length; const char *var; SwfdecAsObject *target; SwfdecAsValue val; SortOption options_; gboolean descending; g_return_if_fail (SWFDEC_IS_AS_CONTEXT (cx)); g_return_if_fail (SWFDEC_IS_AS_OBJECT (object)); g_return_if_fail (options != NULL); g_return_if_fail (custom_function == NULL || SWFDEC_IS_AS_FUNCTION (custom_function)); g_return_if_fail (fields == NULL || fields[0] != NULL); length = swfdec_as_array_length (object); if (length == 0) { // special case for empty array, because g_try_new0 would return NULL SWFDEC_AS_VALUE_SET_OBJECT (ret, object); return; } if (!swfdec_as_context_try_use_mem (cx, sizeof (SortEntry) * length)) { SWFDEC_WARNING ("Array not sorted, too big (%i elements)", length); SWFDEC_AS_VALUE_SET_OBJECT (ret, object); return; } // FIXME: this should be different, but context's memory management is not // done properly yet array = g_try_new0 (SortEntry, length); if (!array) { SWFDEC_WARNING ("Array not sorted, too big (%i elements)", length); SWFDEC_AS_VALUE_SET_OBJECT (ret, object); goto done; } for (i = 0; i < length; i++) { array[i].index_ = i; } // collect values and indexes to the array collect_data.length = length; collect_data.array = array; swfdec_as_object_foreach (object, swfdec_as_array_foreach_sort_collect, &collect_data); // sort the array compare_data.context = cx; compare_data.fields = fields; compare_data.options = options; // if no fields, then we'll do descending here after the sort if (fields == NULL && options[0] & SORT_OPTION_DESCENDING) { descending = TRUE; options_ = options[0] & ~SORT_OPTION_DESCENDING; compare_data.options = &options_; } else { descending = FALSE; } compare_data.custom_function = custom_function; compare_data.equal_found = FALSE; swfdec_as_array_sort_array (array, length, swfdec_as_array_sort_compare, &compare_data); // check unique sort if (options[0] & SORT_OPTION_UNIQUESORT) { if (fields == NULL && custom_function != NULL) { // if we used custom_function for comparision, we shall now go trough the // sorted array and compare them using the default array sort comparision // and use that to decide if it's unique (no it doesn't make too much // sense) for (i = 0; i < length - 1; i++) { SwfdecAsValue *a = &array[i].value; SwfdecAsValue *b = &array[i + 1].value; if (swfdec_as_array_sort_compare_values (cx, a, b, 0, NULL) == 0) break; } if (i < length - 1) { SWFDEC_AS_VALUE_SET_INT (ret, 0); goto done; } } else if (compare_data.equal_found) { SWFDEC_AS_VALUE_SET_INT (ret, 0); goto done; } } if (options[0] & SORT_OPTION_RETURNINDEXEDARRAY) { target = swfdec_as_array_new (cx); if (!target) goto done; } else { target = object; } for (i = 0; i < length; i++) { SortEntry *entry = &array[i]; // set only the values that have new indexes if (!(options[0] & SORT_OPTION_RETURNINDEXEDARRAY) && entry->index_ == (descending ? length - i - 1 : i)) continue; var = swfdec_as_integer_to_string (cx, (descending ? length - i - 1 : i)); if (options[0] & SORT_OPTION_RETURNINDEXEDARRAY) { SWFDEC_AS_VALUE_SET_INT (&val, entry->index_); swfdec_as_object_set_variable (target, var, &val); } else { swfdec_as_object_set_variable (target, var, &entry->value); } } SWFDEC_AS_VALUE_SET_OBJECT (ret, target); done: g_free (array); swfdec_as_context_unuse_mem (cx, sizeof (SortEntry) * length); }