Ottie: Add
This commit is contained in:
@@ -1109,7 +1109,7 @@ libgtk = library('gtk-4',
|
||||
c_args: gtk_cargs + common_cflags,
|
||||
include_directories: [confinc, gdkinc, gskinc, gtkinc],
|
||||
dependencies: gtk_deps + [libgtk_css_dep, libgdk_dep, libgsk_dep],
|
||||
link_whole: [libgtk_css, libgdk, libgsk, ],
|
||||
link_whole: [libgtk_css, libgdk, libgsk, libottie],
|
||||
link_args: common_ldflags,
|
||||
darwin_versions: darwin_versions,
|
||||
install: true,
|
||||
|
||||
@@ -677,6 +677,7 @@ endif
|
||||
subdir('gtk/css')
|
||||
subdir('gdk')
|
||||
subdir('gsk')
|
||||
subdir('ottie')
|
||||
subdir('gtk')
|
||||
subdir('modules')
|
||||
if get_option('demos')
|
||||
|
||||
67
ottie/meson.build
Normal file
67
ottie/meson.build
Normal file
@@ -0,0 +1,67 @@
|
||||
ottie_public_sources = files([
|
||||
'ottiecreation.c',
|
||||
'ottiepaintable.c',
|
||||
'ottieplayer.c',
|
||||
])
|
||||
|
||||
ottie_private_sources = files([
|
||||
'ottiecolorvalue.c',
|
||||
'ottiedoublevalue.c',
|
||||
'ottiefillshape.c',
|
||||
'ottiegroupshape.c',
|
||||
'ottielayer.c',
|
||||
'ottieparser.c',
|
||||
'ottiepathshape.c',
|
||||
'ottiepathvalue.c',
|
||||
'ottiepointvalue.c',
|
||||
'ottiepoint3dvalue.c',
|
||||
'ottieprecomp.c',
|
||||
'ottieprecomplayer.c',
|
||||
'ottierectshape.c',
|
||||
'ottieshape.c',
|
||||
'ottieshapelayer.c',
|
||||
'ottiestrokeshape.c',
|
||||
'ottietransform.c',
|
||||
'ottietrimshape.c',
|
||||
])
|
||||
|
||||
ottie_public_headers = files([
|
||||
'ottie.h',
|
||||
'ottiecreation.h',
|
||||
'ottiepaintable.h',
|
||||
'ottieplayer.h',
|
||||
])
|
||||
|
||||
install_headers(ottie_public_headers, 'ottie.h', subdir: 'gtk-4.0/ottie')
|
||||
|
||||
json_glib_dep = dependency('json-glib-1.0', required: true)
|
||||
ottie_deps = [
|
||||
libm,
|
||||
glib_dep,
|
||||
gobject_dep,
|
||||
platform_gio_dep,
|
||||
libgdk_dep,
|
||||
libgsk_dep,
|
||||
json_glib_dep
|
||||
]
|
||||
|
||||
libottie = static_library('ottie',
|
||||
sources: [
|
||||
ottie_public_sources,
|
||||
ottie_private_sources,
|
||||
],
|
||||
dependencies: ottie_deps,
|
||||
include_directories: [ confinc, ],
|
||||
c_args: [
|
||||
'-DGTK_COMPILATION',
|
||||
'-DG_LOG_DOMAIN="Gtk"',
|
||||
] + common_cflags,
|
||||
link_with: [libgdk, libgsk ],
|
||||
link_args: common_ldflags)
|
||||
|
||||
# We don't have link_with: to internal static libs here on purpose, just
|
||||
# list the dependencies and generated headers and such, for use in the
|
||||
# "public" libgtk_dep used by internal executables.
|
||||
libottie_dep = declare_dependency(include_directories: [ confinc, ],
|
||||
dependencies: ottie_deps)
|
||||
|
||||
31
ottie/ottie.h
Normal file
31
ottie/ottie.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_H__
|
||||
#define __OTTIE_H__
|
||||
|
||||
#define __OTTIE_H_INSIDE__
|
||||
|
||||
#include <ottie/ottiecreation.h>
|
||||
#include <ottie/ottiepaintable.h>
|
||||
#include <ottie/ottieplayer.h>
|
||||
|
||||
#undef __OTTIE_H_INSIDE__
|
||||
|
||||
#endif /* __OTTIE_H__ */
|
||||
149
ottie/ottiecolorvalue.c
Normal file
149
ottie/ottiecolorvalue.c
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottiecolorvalueprivate.h"
|
||||
|
||||
#include "ottieparserprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
static gboolean
|
||||
ottie_color_value_parse_one (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
GdkRGBA *rgba = (GdkRGBA *) ((guint8 *) data + offset);
|
||||
double d[3];
|
||||
|
||||
if (!ottie_parser_parse_array (reader, "color value",
|
||||
3, 3, NULL,
|
||||
0, sizeof (double),
|
||||
ottie_parser_option_double,
|
||||
d))
|
||||
{
|
||||
d[0] = d[1] = d[2] = 0;
|
||||
}
|
||||
|
||||
rgba->red = d[0];
|
||||
rgba->green = d[1];
|
||||
rgba->blue = d[2];
|
||||
rgba->alpha = 1;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_color_value_interpolate (const GdkRGBA *start,
|
||||
const GdkRGBA *end,
|
||||
double progress,
|
||||
GdkRGBA *result)
|
||||
{
|
||||
result->red = start->red + progress * (end->red - start->red);
|
||||
result->green = start->green + progress * (end->green - start->green);
|
||||
result->blue = start->blue + progress * (end->blue - start->blue);
|
||||
result->alpha = start->alpha + progress * (end->alpha - start->alpha);
|
||||
}
|
||||
|
||||
#define OTTIE_KEYFRAMES_NAME ottie_color_keyframes
|
||||
#define OTTIE_KEYFRAMES_TYPE_NAME OttieColorKeyframes
|
||||
#define OTTIE_KEYFRAMES_ELEMENT_TYPE GdkRGBA
|
||||
#define OTTIE_KEYFRAMES_BY_VALUE 1
|
||||
#define OTTIE_KEYFRAMES_DIMENSIONS 4
|
||||
#define OTTIE_KEYFRAMES_PARSE_FUNC ottie_color_value_parse_one
|
||||
#define OTTIE_KEYFRAMES_INTERPOLATE_FUNC ottie_color_value_interpolate
|
||||
#include "ottiekeyframesimpl.c"
|
||||
|
||||
void
|
||||
ottie_color_value_init (OttieColorValue *self,
|
||||
const GdkRGBA *value)
|
||||
{
|
||||
self->is_static = TRUE;
|
||||
self->static_value = *value;
|
||||
}
|
||||
|
||||
void
|
||||
ottie_color_value_clear (OttieColorValue *self)
|
||||
{
|
||||
if (!self->is_static)
|
||||
g_clear_pointer (&self->keyframes, ottie_color_keyframes_free);
|
||||
}
|
||||
|
||||
void
|
||||
ottie_color_value_get (OttieColorValue *self,
|
||||
double timestamp,
|
||||
GdkRGBA *rgba)
|
||||
{
|
||||
if (self->is_static)
|
||||
{
|
||||
*rgba = self->static_value;
|
||||
return;
|
||||
}
|
||||
|
||||
ottie_color_keyframes_get (self->keyframes, timestamp, rgba);
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_color_value_parse (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttieColorValue *self = (OttieColorValue *) ((guint8 *) data + offset);
|
||||
|
||||
if (json_reader_read_member (reader, "k"))
|
||||
{
|
||||
gboolean is_static;
|
||||
|
||||
if (!json_reader_is_array (reader))
|
||||
is_static = TRUE;
|
||||
else
|
||||
{
|
||||
if (json_reader_read_element (reader, 0))
|
||||
is_static = !json_reader_is_object (reader);
|
||||
else
|
||||
is_static = TRUE;
|
||||
json_reader_end_element (reader);
|
||||
}
|
||||
|
||||
if (is_static)
|
||||
{
|
||||
self->is_static = TRUE;
|
||||
ottie_color_value_parse_one (reader, 0, &self->static_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->is_static = FALSE;
|
||||
self->keyframes = ottie_color_keyframes_parse (reader);
|
||||
if (self->keyframes == NULL)
|
||||
{
|
||||
json_reader_end_member (reader);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "Property is not a color value");
|
||||
}
|
||||
json_reader_end_member (reader);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
54
ottie/ottiecolorvalueprivate.h
Normal file
54
ottie/ottiecolorvalueprivate.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_COLOR_VALUE_PRIVATE_H__
|
||||
#define __OTTIE_COLOR_VALUE_PRIVATE_H__
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _OttieColorValue OttieColorValue;
|
||||
|
||||
struct _OttieColorValue
|
||||
{
|
||||
gboolean is_static;
|
||||
union {
|
||||
GdkRGBA static_value;
|
||||
gpointer keyframes;
|
||||
};
|
||||
};
|
||||
|
||||
void ottie_color_value_init (OttieColorValue *self,
|
||||
const GdkRGBA *rgba);
|
||||
void ottie_color_value_clear (OttieColorValue *self);
|
||||
|
||||
void ottie_color_value_get (OttieColorValue *self,
|
||||
double timestamp,
|
||||
GdkRGBA *rgba);
|
||||
|
||||
gboolean ottie_color_value_parse (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_COLOR_VALUE_PRIVATE_H__ */
|
||||
659
ottie/ottiecreation.c
Normal file
659
ottie/ottiecreation.c
Normal file
@@ -0,0 +1,659 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottiecreationprivate.h"
|
||||
|
||||
#include "ottielayerprivate.h"
|
||||
#include "ottieparserprivate.h"
|
||||
#include "ottieprecompprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
struct _OttieCreation
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
char *name;
|
||||
double frame_rate;
|
||||
double start_frame;
|
||||
double end_frame;
|
||||
double width;
|
||||
double height;
|
||||
|
||||
OttiePrecomp *layers;
|
||||
GHashTable *precomp_assets;
|
||||
|
||||
GCancellable *cancellable;
|
||||
};
|
||||
|
||||
struct _OttieCreationClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_END_FRAME,
|
||||
PROP_FRAME_RATE,
|
||||
PROP_HEIGHT,
|
||||
PROP_LOADING,
|
||||
PROP_NAME,
|
||||
PROP_PREPARED,
|
||||
PROP_START_FRAME,
|
||||
PROP_WIDTH,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
G_DEFINE_TYPE (OttieCreation, ottie_creation, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
ottie_creation_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
|
||||
{
|
||||
//OttieCreation *self = OTTIE_CREATION (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_creation_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
OttieCreation *self = OTTIE_CREATION (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_END_FRAME:
|
||||
g_value_set_double (value, self->end_frame);
|
||||
break;
|
||||
|
||||
case PROP_FRAME_RATE:
|
||||
g_value_set_double (value, self->frame_rate);
|
||||
break;
|
||||
|
||||
case PROP_HEIGHT:
|
||||
g_value_set_double (value, self->height);
|
||||
break;
|
||||
|
||||
case PROP_PREPARED:
|
||||
g_value_set_boolean (value, self->cancellable != NULL);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, self->name);
|
||||
break;
|
||||
|
||||
case PROP_START_FRAME:
|
||||
g_value_set_double (value, self->start_frame);
|
||||
break;
|
||||
|
||||
case PROP_WIDTH:
|
||||
g_value_set_double (value, self->width);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_creation_stop_loading (OttieCreation *self,
|
||||
gboolean emit)
|
||||
{
|
||||
if (self->cancellable == NULL)
|
||||
return;
|
||||
|
||||
g_cancellable_cancel (self->cancellable);
|
||||
g_clear_object (&self->cancellable);
|
||||
|
||||
if (emit)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LOADING]);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_creation_reset (OttieCreation *self)
|
||||
{
|
||||
g_clear_object (&self->layers);
|
||||
g_hash_table_remove_all (self->precomp_assets);
|
||||
|
||||
g_clear_pointer (&self->name, g_free);
|
||||
self->frame_rate = 0;
|
||||
self->start_frame = 0;
|
||||
self->end_frame = 0;
|
||||
self->width = 0;
|
||||
self->height = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_creation_dispose (GObject *object)
|
||||
{
|
||||
OttieCreation *self = OTTIE_CREATION (object);
|
||||
|
||||
ottie_creation_stop_loading (self, FALSE);
|
||||
ottie_creation_reset (self);
|
||||
|
||||
G_OBJECT_CLASS (ottie_creation_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_creation_finalize (GObject *object)
|
||||
{
|
||||
OttieCreation *self = OTTIE_CREATION (object);
|
||||
|
||||
g_hash_table_unref (self->precomp_assets);
|
||||
|
||||
G_OBJECT_CLASS (ottie_creation_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_creation_class_init (OttieCreationClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
|
||||
gobject_class->set_property = ottie_creation_set_property;
|
||||
gobject_class->get_property = ottie_creation_get_property;
|
||||
gobject_class->finalize = ottie_creation_finalize;
|
||||
gobject_class->dispose = ottie_creation_dispose;
|
||||
|
||||
/**
|
||||
* OttieCreation:end-frame:
|
||||
*
|
||||
* End frame of the creation
|
||||
*/
|
||||
properties[PROP_END_FRAME] =
|
||||
g_param_spec_double ("end-frame",
|
||||
"End frame",
|
||||
"End frame of the creation",
|
||||
0.0, G_MAXDOUBLE, 0.0,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* OttieCreation:loading:
|
||||
*
|
||||
* Whether the creation is currently loading.
|
||||
*/
|
||||
properties[PROP_LOADING] =
|
||||
g_param_spec_boolean ("loading",
|
||||
"Loading",
|
||||
"Whether the creation is currently loading",
|
||||
FALSE,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* OttieCreation:frame-rate:
|
||||
*
|
||||
* Frame rate of this creation
|
||||
*/
|
||||
properties[PROP_FRAME_RATE] =
|
||||
g_param_spec_double ("frame-rate",
|
||||
"Frame rate",
|
||||
"Frame rate of this creation",
|
||||
0.0, G_MAXDOUBLE, 0.0,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* OttieCreation:height:
|
||||
*
|
||||
* Height of this creation
|
||||
*/
|
||||
properties[PROP_HEIGHT] =
|
||||
g_param_spec_double ("height",
|
||||
"Height",
|
||||
"Height of this creation",
|
||||
0.0, G_MAXDOUBLE, 0.0,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* OttieCreation:name:
|
||||
*
|
||||
* The name of the creation.
|
||||
*/
|
||||
properties[PROP_NAME] =
|
||||
g_param_spec_string ("name",
|
||||
"Name",
|
||||
"The name of the creation",
|
||||
NULL,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* OttieCreation:prepared:
|
||||
*
|
||||
* Whether the creation is prepared to render
|
||||
*/
|
||||
properties[PROP_PREPARED] =
|
||||
g_param_spec_boolean ("prepared",
|
||||
"Prepared",
|
||||
"Whether the creation is prepared to render",
|
||||
FALSE,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* OttieCreation:start-frame:
|
||||
*
|
||||
* Start frame of the creation
|
||||
*/
|
||||
properties[PROP_START_FRAME] =
|
||||
g_param_spec_double ("start-frame",
|
||||
"Start frame",
|
||||
"Start frame of the creation",
|
||||
0.0, G_MAXDOUBLE, 0.0,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* OttieCreation:width:
|
||||
*
|
||||
* Width of this creation
|
||||
*/
|
||||
properties[PROP_WIDTH] =
|
||||
g_param_spec_double ("width",
|
||||
"Width",
|
||||
"Width of this creation",
|
||||
0.0, G_MAXDOUBLE, 0.0,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_creation_init (OttieCreation *self)
|
||||
{
|
||||
self->precomp_assets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_creation_is_loading:
|
||||
* @self: a #OttieCreation
|
||||
*
|
||||
* Returns whether @self is still in the process of loading. This may not just involve
|
||||
* the creation itself, but also any assets that are a part of the creation.
|
||||
*
|
||||
* Returns: %TRUE if the creation is loading
|
||||
*/
|
||||
gboolean
|
||||
ottie_creation_is_loading (OttieCreation *self)
|
||||
{
|
||||
g_return_val_if_fail (OTTIE_IS_CREATION (self), FALSE);
|
||||
|
||||
return self->cancellable != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_creation_is_prepared:
|
||||
* @self: a #OttieCreation
|
||||
*
|
||||
* Returns whether @self has successfully loaded a document that it can display.
|
||||
*
|
||||
* Returns: %TRUE if the creation can be used
|
||||
*/
|
||||
gboolean
|
||||
ottie_creation_is_prepared (OttieCreation *self)
|
||||
{
|
||||
g_return_val_if_fail (OTTIE_IS_CREATION (self), FALSE);
|
||||
|
||||
return self->frame_rate > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_creation_get_name:
|
||||
* @self: a #OttieCreation
|
||||
*
|
||||
* Returns the name of the current creation or %NULL if the creation is unnamed.
|
||||
*
|
||||
* Returns: (allow-none): The name of the creation
|
||||
*/
|
||||
const char *
|
||||
ottie_creation_get_name (OttieCreation *self)
|
||||
{
|
||||
g_return_val_if_fail (OTTIE_IS_CREATION (self), FALSE);
|
||||
|
||||
return self->name;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_creation_emit_error (OttieCreation *self,
|
||||
const GError *error)
|
||||
{
|
||||
g_print ("Ottie is sad: %s\n", error->message);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char *id;
|
||||
OttiePrecomp *precomp;
|
||||
} OttieParserAsset;
|
||||
|
||||
static gboolean
|
||||
ottie_creation_parse_asset (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttieParserOption options[] = {
|
||||
{ "id", ottie_parser_option_string, G_STRUCT_OFFSET (OttieParserAsset, id) },
|
||||
{ "layers", ottie_precomp_parse_layers, G_STRUCT_OFFSET (OttieParserAsset, precomp) },
|
||||
};
|
||||
OttieCreation *self = data;
|
||||
OttieParserAsset asset = { };
|
||||
gboolean result;
|
||||
|
||||
result = ottie_parser_parse_object (reader, "asset", options, G_N_ELEMENTS (options), &asset);
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (asset.id == NULL)
|
||||
ottie_parser_error_syntax (reader, "No name given to asset");
|
||||
else if (asset.precomp == NULL)
|
||||
ottie_parser_error_syntax (reader, "No precomp layer or image asset defined for name %s", asset.id);
|
||||
else
|
||||
g_hash_table_insert (self->precomp_assets, g_strdup (asset.id), g_object_ref (asset.precomp));
|
||||
}
|
||||
|
||||
g_clear_pointer (&asset.id, g_free);
|
||||
g_clear_object (&asset.precomp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_creation_parse_assets (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
return ottie_parser_parse_array (reader, "assets",
|
||||
0, G_MAXUINT, NULL,
|
||||
offset, 0,
|
||||
ottie_creation_parse_asset,
|
||||
data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_creation_parse_marker (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
ottie_parser_error_unsupported (reader, "Markers are not implemented yet.");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_creation_parse_markers (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
return ottie_parser_parse_array (reader, "markers",
|
||||
0, G_MAXUINT, NULL,
|
||||
offset, 0,
|
||||
ottie_creation_parse_marker,
|
||||
data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_creation_load_from_reader (OttieCreation *self,
|
||||
JsonReader *reader)
|
||||
{
|
||||
OttieParserOption options[] = {
|
||||
{ "fr", ottie_parser_option_double, G_STRUCT_OFFSET (OttieCreation, frame_rate) },
|
||||
{ "w", ottie_parser_option_double, G_STRUCT_OFFSET (OttieCreation, width) },
|
||||
{ "h", ottie_parser_option_double, G_STRUCT_OFFSET (OttieCreation, height) },
|
||||
{ "nm", ottie_parser_option_string, G_STRUCT_OFFSET (OttieCreation, name) },
|
||||
{ "ip", ottie_parser_option_double, G_STRUCT_OFFSET (OttieCreation, start_frame) },
|
||||
{ "op", ottie_parser_option_double, G_STRUCT_OFFSET (OttieCreation, end_frame) },
|
||||
{ "ddd", ottie_parser_option_3d, 0 },
|
||||
{ "v", ottie_parser_option_skip, 0 },
|
||||
{ "layers", ottie_precomp_parse_layers, G_STRUCT_OFFSET (OttieCreation, layers) },
|
||||
{ "assets", ottie_creation_parse_assets, 0 },
|
||||
{ "markers", ottie_creation_parse_markers, 0 },
|
||||
};
|
||||
|
||||
return ottie_parser_parse_object (reader, "toplevel", options, G_N_ELEMENTS (options), self);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_creation_notify_prepared (OttieCreation *self)
|
||||
{
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PREPARED]);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FRAME_RATE]);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WIDTH]);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HEIGHT]);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_START_FRAME]);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_END_FRAME]);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_creation_load_from_node (OttieCreation *self,
|
||||
JsonNode *root)
|
||||
{
|
||||
JsonReader *reader = json_reader_new (root);
|
||||
|
||||
ottie_creation_load_from_reader (self, reader);
|
||||
|
||||
g_object_unref (reader);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_creation_load_file_parsed (GObject *parser,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
OttieCreation *self = data;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!json_parser_load_from_stream_finish (JSON_PARSER (parser), res, &error))
|
||||
{
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
ottie_creation_emit_error (self, error);
|
||||
g_error_free (error);
|
||||
ottie_creation_stop_loading (self, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
ottie_creation_load_from_node (self, json_parser_get_root (JSON_PARSER (parser)));
|
||||
ottie_creation_stop_loading (self, TRUE);
|
||||
ottie_creation_notify_prepared (self);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_creation_load_file_open (GObject *file,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
OttieCreation *self = data;
|
||||
GFileInputStream *stream;
|
||||
GError *error = NULL;
|
||||
JsonParser *parser;
|
||||
|
||||
stream = g_file_read_finish (G_FILE (file), res, &error);
|
||||
if (stream == NULL)
|
||||
{
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
ottie_creation_emit_error (self, error);
|
||||
g_error_free (error);
|
||||
ottie_creation_stop_loading (self, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
parser = json_parser_new ();
|
||||
json_parser_load_from_stream_async (parser,
|
||||
G_INPUT_STREAM (stream),
|
||||
self->cancellable,
|
||||
ottie_creation_load_file_parsed,
|
||||
self);
|
||||
g_object_unref (parser);
|
||||
}
|
||||
|
||||
void
|
||||
ottie_creation_load_file (OttieCreation *self,
|
||||
GFile *file)
|
||||
{
|
||||
g_return_if_fail (OTTIE_IS_CREATION (self));
|
||||
g_return_if_fail (G_IS_FILE (file));
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
ottie_creation_stop_loading (self, FALSE);
|
||||
if (self->frame_rate)
|
||||
{
|
||||
ottie_creation_reset (self);
|
||||
ottie_creation_notify_prepared (self);
|
||||
}
|
||||
|
||||
self->cancellable = g_cancellable_new ();
|
||||
|
||||
g_file_read_async (file,
|
||||
G_PRIORITY_DEFAULT,
|
||||
self->cancellable,
|
||||
ottie_creation_load_file_open,
|
||||
self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LOADING]);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
}
|
||||
|
||||
void
|
||||
ottie_creation_load_filename (OttieCreation *self,
|
||||
const char *filename)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
g_return_if_fail (OTTIE_IS_CREATION (self));
|
||||
g_return_if_fail (filename != NULL);
|
||||
|
||||
file = g_file_new_for_path (filename);
|
||||
|
||||
ottie_creation_load_file (self, file);
|
||||
|
||||
g_clear_object (&file);
|
||||
}
|
||||
|
||||
OttieCreation *
|
||||
ottie_creation_new (void)
|
||||
{
|
||||
return g_object_new (OTTIE_TYPE_CREATION, NULL);
|
||||
}
|
||||
|
||||
OttieCreation *
|
||||
ottie_creation_new_for_file (GFile *file)
|
||||
{
|
||||
OttieCreation *self;
|
||||
|
||||
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||
|
||||
self = g_object_new (OTTIE_TYPE_CREATION, NULL);
|
||||
|
||||
ottie_creation_load_file (self, file);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
OttieCreation *
|
||||
ottie_creation_new_for_filename (const char *filename)
|
||||
{
|
||||
OttieCreation *self;
|
||||
GFile *file;
|
||||
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
|
||||
file = g_file_new_for_path (filename);
|
||||
|
||||
self = ottie_creation_new_for_file (file);
|
||||
|
||||
g_clear_object (&file);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
double
|
||||
ottie_creation_get_frame_rate (OttieCreation *self)
|
||||
{
|
||||
g_return_val_if_fail (OTTIE_IS_CREATION (self), 0);
|
||||
|
||||
return self->frame_rate;
|
||||
}
|
||||
|
||||
double
|
||||
ottie_creation_get_start_frame (OttieCreation *self)
|
||||
{
|
||||
g_return_val_if_fail (OTTIE_IS_CREATION (self), 0);
|
||||
|
||||
return self->start_frame;
|
||||
}
|
||||
|
||||
double
|
||||
ottie_creation_get_end_frame (OttieCreation *self)
|
||||
{
|
||||
g_return_val_if_fail (OTTIE_IS_CREATION (self), 0);
|
||||
|
||||
return self->end_frame;
|
||||
}
|
||||
|
||||
double
|
||||
ottie_creation_get_width (OttieCreation *self)
|
||||
{
|
||||
g_return_val_if_fail (OTTIE_IS_CREATION (self), 0);
|
||||
|
||||
return self->width;
|
||||
}
|
||||
|
||||
double
|
||||
ottie_creation_get_height (OttieCreation *self)
|
||||
{
|
||||
g_return_val_if_fail (OTTIE_IS_CREATION (self), 0);
|
||||
|
||||
return self->height;
|
||||
}
|
||||
|
||||
void
|
||||
ottie_creation_snapshot (OttieCreation *self,
|
||||
GtkSnapshot *snapshot,
|
||||
double timestamp)
|
||||
{
|
||||
if (self->layers == NULL)
|
||||
return;
|
||||
|
||||
timestamp = timestamp * self->frame_rate;
|
||||
ottie_layer_snapshot (OTTIE_LAYER (self->layers), snapshot, timestamp);
|
||||
}
|
||||
|
||||
|
||||
80
ottie/ottiecreation.h
Normal file
80
ottie/ottiecreation.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_CREATION_H__
|
||||
#define __OTTIE_CREATION_H__
|
||||
|
||||
#if !defined (__OTTIE_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <ottie/ottie.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OTTIE_TYPE_CREATION (ottie_creation_get_type ())
|
||||
#define OTTIE_CREATION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OTTIE_TYPE_CREATION, OttieCreation))
|
||||
#define OTTIE_CREATION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), OTTIE_TYPE_CREATION, OttieCreationClass))
|
||||
#define OTTIE_IS_CREATION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OTTIE_TYPE_CREATION))
|
||||
#define OTTIE_IS_CREATION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OTTIE_TYPE_CREATION))
|
||||
#define OTTIE_CREATION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OTTIE_TYPE_CREATION, OttieCreationClass))
|
||||
|
||||
typedef struct _OttieCreation OttieCreation;
|
||||
typedef struct _OttieCreationClass OttieCreationClass;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType ottie_creation_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
OttieCreation * ottie_creation_new (void);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
OttieCreation * ottie_creation_new_for_file (GFile *file);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
OttieCreation * ottie_creation_new_for_filename (const char *filename);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void ottie_creation_load_file (OttieCreation *self,
|
||||
GFile *file);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void ottie_creation_load_filename (OttieCreation *self,
|
||||
const char *filename);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean ottie_creation_is_loading (OttieCreation *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean ottie_creation_is_prepared (OttieCreation *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const char * ottie_creation_get_name (OttieCreation *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
double ottie_creation_get_frame_rate (OttieCreation *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
double ottie_creation_get_start_frame (OttieCreation *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
double ottie_creation_get_end_frame (OttieCreation *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
double ottie_creation_get_width (OttieCreation *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
double ottie_creation_get_height (OttieCreation *self);
|
||||
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_CREATION_H__ */
|
||||
36
ottie/ottiecreationprivate.h
Normal file
36
ottie/ottiecreationprivate.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_CREATION_PRIVATE_H__
|
||||
#define __OTTIE_CREATION_PRIVATE_H__
|
||||
|
||||
#include "ottiecreation.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
void ottie_creation_snapshot (OttieCreation *self,
|
||||
GtkSnapshot *snapshot,
|
||||
double timestamp);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_CREATION_PRIVATE_H__ */
|
||||
121
ottie/ottiedoublevalue.c
Normal file
121
ottie/ottiedoublevalue.c
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottiedoublevalueprivate.h"
|
||||
|
||||
#include "ottieparserprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
static gboolean
|
||||
ottie_double_value_parse_value (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
gboolean result, array;
|
||||
|
||||
/* Lottie being Lottie, single values may get dumped into arrays. */
|
||||
array = json_reader_is_array (reader);
|
||||
if (array)
|
||||
json_reader_read_element (reader, 0);
|
||||
|
||||
result = ottie_parser_option_double (reader, offset, data);
|
||||
|
||||
if (array)
|
||||
json_reader_end_element (reader);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static double
|
||||
ottie_double_value_interpolate (double start,
|
||||
double end,
|
||||
double progress)
|
||||
{
|
||||
return start + (end - start) * progress;
|
||||
}
|
||||
|
||||
#define OTTIE_KEYFRAMES_NAME ottie_double_keyframes
|
||||
#define OTTIE_KEYFRAMES_TYPE_NAME OttieDoubleKeyframes
|
||||
#define OTTIE_KEYFRAMES_ELEMENT_TYPE double
|
||||
#define OTTIE_KEYFRAMES_PARSE_FUNC ottie_double_value_parse_value
|
||||
#define OTTIE_KEYFRAMES_INTERPOLATE_FUNC ottie_double_value_interpolate
|
||||
#include "ottiekeyframesimpl.c"
|
||||
|
||||
void
|
||||
ottie_double_value_init (OttieDoubleValue *self,
|
||||
double value)
|
||||
{
|
||||
self->is_static = TRUE;
|
||||
self->static_value = value;
|
||||
}
|
||||
|
||||
void
|
||||
ottie_double_value_clear (OttieDoubleValue *self)
|
||||
{
|
||||
if (!self->is_static)
|
||||
g_clear_pointer (&self->keyframes, ottie_double_keyframes_free);
|
||||
}
|
||||
|
||||
double
|
||||
ottie_double_value_get (OttieDoubleValue *self,
|
||||
double timestamp)
|
||||
{
|
||||
if (self->is_static)
|
||||
return self->static_value;
|
||||
|
||||
return ottie_double_keyframes_get (self->keyframes, timestamp);
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_double_value_parse (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttieDoubleValue *self = (OttieDoubleValue *) ((guint8 *) data + GPOINTER_TO_SIZE (offset));
|
||||
|
||||
if (json_reader_read_member (reader, "k"))
|
||||
{
|
||||
if (!json_reader_is_array (reader))
|
||||
{
|
||||
self->is_static = TRUE;
|
||||
self->static_value = json_reader_get_double_value (reader);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->is_static = FALSE;
|
||||
self->keyframes = ottie_double_keyframes_parse (reader);
|
||||
if (self->keyframes == NULL)
|
||||
{
|
||||
json_reader_end_member (reader);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "Property is not a number");
|
||||
}
|
||||
json_reader_end_member (reader);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
51
ottie/ottiedoublevalueprivate.h
Normal file
51
ottie/ottiedoublevalueprivate.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_DOUBLE_VALUE_PRIVATE_H__
|
||||
#define __OTTIE_DOUBLE_VALUE_PRIVATE_H__
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _OttieDoubleValue OttieDoubleValue;
|
||||
|
||||
struct _OttieDoubleValue
|
||||
{
|
||||
gboolean is_static;
|
||||
union {
|
||||
double static_value;
|
||||
gpointer keyframes;
|
||||
};
|
||||
};
|
||||
|
||||
void ottie_double_value_init (OttieDoubleValue *self,
|
||||
double value);
|
||||
void ottie_double_value_clear (OttieDoubleValue *self);
|
||||
|
||||
double ottie_double_value_get (OttieDoubleValue *self,
|
||||
double timestamp);
|
||||
|
||||
gboolean ottie_double_value_parse (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_DOUBLE_VALUE_PRIVATE_H__ */
|
||||
135
ottie/ottiefillshape.c
Normal file
135
ottie/ottiefillshape.c
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottiefillshapeprivate.h"
|
||||
|
||||
#include "ottiecolorvalueprivate.h"
|
||||
#include "ottiedoublevalueprivate.h"
|
||||
#include "ottieparserprivate.h"
|
||||
#include "ottieshapeprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gsk/gsk.h>
|
||||
|
||||
struct _OttieFillShape
|
||||
{
|
||||
OttieShape parent;
|
||||
|
||||
OttieDoubleValue opacity;
|
||||
OttieColorValue color;
|
||||
GskBlendMode blend_mode;
|
||||
};
|
||||
|
||||
struct _OttieFillShapeClass
|
||||
{
|
||||
OttieShapeClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (OttieFillShape, ottie_fill_shape, OTTIE_TYPE_SHAPE)
|
||||
|
||||
static void
|
||||
ottie_fill_shape_snapshot (OttieShape *shape,
|
||||
GtkSnapshot *snapshot,
|
||||
OttieShapeSnapshot *snapshot_data,
|
||||
double timestamp)
|
||||
{
|
||||
OttieFillShape *self = OTTIE_FILL_SHAPE (shape);
|
||||
GskPath *path;
|
||||
graphene_rect_t bounds;
|
||||
GdkRGBA color;
|
||||
double opacity;
|
||||
|
||||
opacity = ottie_double_value_get (&self->opacity, timestamp);
|
||||
opacity = CLAMP (opacity, 0, 100);
|
||||
ottie_color_value_get (&self->color, timestamp, &color);
|
||||
color.alpha = color.alpha * opacity / 100.f;
|
||||
if (gdk_rgba_is_clear (&color))
|
||||
return;
|
||||
|
||||
path = ottie_shape_snapshot_get_path (snapshot_data);
|
||||
gtk_snapshot_push_fill (snapshot, path, GSK_FILL_RULE_WINDING);
|
||||
|
||||
gsk_path_get_bounds (path, &bounds);
|
||||
gtk_snapshot_append_color (snapshot, &color, &bounds);
|
||||
|
||||
gtk_snapshot_pop (snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_fill_shape_dispose (GObject *object)
|
||||
{
|
||||
OttieFillShape *self = OTTIE_FILL_SHAPE (object);
|
||||
|
||||
ottie_double_value_clear (&self->opacity);
|
||||
ottie_color_value_clear (&self->color);
|
||||
|
||||
G_OBJECT_CLASS (ottie_fill_shape_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_fill_shape_finalize (GObject *object)
|
||||
{
|
||||
//OttieFillShape *self = OTTIE_FILL_SHAPE (object);
|
||||
|
||||
G_OBJECT_CLASS (ottie_fill_shape_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_fill_shape_class_init (OttieFillShapeClass *klass)
|
||||
{
|
||||
OttieShapeClass *shape_class = OTTIE_SHAPE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
shape_class->snapshot = ottie_fill_shape_snapshot;
|
||||
|
||||
gobject_class->finalize = ottie_fill_shape_finalize;
|
||||
gobject_class->dispose = ottie_fill_shape_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_fill_shape_init (OttieFillShape *self)
|
||||
{
|
||||
ottie_double_value_init (&self->opacity, 100);
|
||||
ottie_color_value_init (&self->color, &(GdkRGBA) { 0, 0, 0, 1 });
|
||||
}
|
||||
|
||||
OttieShape *
|
||||
ottie_fill_shape_parse (JsonReader *reader)
|
||||
{
|
||||
OttieParserOption options[] = {
|
||||
OTTIE_PARSE_OPTIONS_SHAPE
|
||||
{ "o", ottie_double_value_parse, G_STRUCT_OFFSET (OttieFillShape, opacity) },
|
||||
{ "c", ottie_color_value_parse, G_STRUCT_OFFSET (OttieFillShape, color) },
|
||||
{ "bm", ottie_parser_option_blend_mode, G_STRUCT_OFFSET (OttieFillShape, blend_mode) },
|
||||
};
|
||||
OttieFillShape *self;
|
||||
|
||||
self = g_object_new (OTTIE_TYPE_FILL_SHAPE, NULL);
|
||||
|
||||
if (!ottie_parser_parse_object (reader, "fill shape", options, G_N_ELEMENTS (options), self))
|
||||
{
|
||||
g_object_unref (self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return OTTIE_SHAPE (self);
|
||||
}
|
||||
|
||||
45
ottie/ottiefillshapeprivate.h
Normal file
45
ottie/ottiefillshapeprivate.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_FILL_SHAPE_PRIVATE_H__
|
||||
#define __OTTIE_FILL_SHAPE_PRIVATE_H__
|
||||
|
||||
#include "ottieshapeprivate.h"
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OTTIE_TYPE_FILL_SHAPE (ottie_fill_shape_get_type ())
|
||||
#define OTTIE_FILL_SHAPE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OTTIE_TYPE_FILL_SHAPE, OttieFillShape))
|
||||
#define OTTIE_FILL_SHAPE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), OTTIE_TYPE_FILL_SHAPE, OttieFillShapeClass))
|
||||
#define OTTIE_IS_FILL_SHAPE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OTTIE_TYPE_FILL_SHAPE))
|
||||
#define OTTIE_IS_FILL_SHAPE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OTTIE_TYPE_FILL_SHAPE))
|
||||
#define OTTIE_FILL_SHAPE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OTTIE_TYPE_FILL_SHAPE, OttieFillShapeClass))
|
||||
|
||||
typedef struct _OttieFillShape OttieFillShape;
|
||||
typedef struct _OttieFillShapeClass OttieFillShapeClass;
|
||||
|
||||
GType ottie_fill_shape_get_type (void) G_GNUC_CONST;
|
||||
|
||||
OttieShape * ottie_fill_shape_parse (JsonReader *reader);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_FILL_SHAPE_PRIVATE_H__ */
|
||||
235
ottie/ottiegroupshape.c
Normal file
235
ottie/ottiegroupshape.c
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottiegroupshapeprivate.h"
|
||||
|
||||
#include "ottiefillshapeprivate.h"
|
||||
#include "ottieparserprivate.h"
|
||||
#include "ottiepathshapeprivate.h"
|
||||
#include "ottierectshapeprivate.h"
|
||||
#include "ottieshapeprivate.h"
|
||||
#include "ottiestrokeshapeprivate.h"
|
||||
#include "ottietransformprivate.h"
|
||||
#include "ottietrimshapeprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gsk/gsk.h>
|
||||
|
||||
#define GDK_ARRAY_ELEMENT_TYPE OttieShape *
|
||||
#define GDK_ARRAY_FREE_FUNC g_object_unref
|
||||
#define GDK_ARRAY_TYPE_NAME OttieShapeList
|
||||
#define GDK_ARRAY_NAME ottie_shape_list
|
||||
#define GDK_ARRAY_PREALLOC 4
|
||||
#include "gdk/gdkarrayimpl.c"
|
||||
|
||||
struct _OttieGroupShape
|
||||
{
|
||||
OttieShape parent;
|
||||
|
||||
OttieShapeList shapes;
|
||||
GskBlendMode blend_mode;
|
||||
};
|
||||
|
||||
struct _OttieGroupShapeClass
|
||||
{
|
||||
OttieShapeClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (OttieGroupShape, ottie_group_shape, OTTIE_TYPE_SHAPE)
|
||||
|
||||
static void
|
||||
ottie_group_shape_snapshot (OttieShape *shape,
|
||||
GtkSnapshot *snapshot,
|
||||
OttieShapeSnapshot *snapshot_data,
|
||||
double timestamp)
|
||||
{
|
||||
OttieGroupShape *self = OTTIE_GROUP_SHAPE (shape);
|
||||
OttieShapeSnapshot group_snapshot;
|
||||
|
||||
gtk_snapshot_save (snapshot);
|
||||
|
||||
ottie_shape_snapshot_init (&group_snapshot, snapshot_data);
|
||||
|
||||
for (gsize i = 0; i < ottie_shape_list_get_size (&self->shapes); i++)
|
||||
{
|
||||
OttieShape *tr_shape = ottie_shape_list_get (&self->shapes, i);
|
||||
|
||||
if (OTTIE_IS_TRANSFORM (tr_shape))
|
||||
{
|
||||
GskTransform *transform = ottie_transform_get_transform (OTTIE_TRANSFORM (tr_shape), timestamp);
|
||||
gtk_snapshot_transform (snapshot, transform);
|
||||
gsk_transform_unref (transform);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (gsize i = 0; i < ottie_shape_list_get_size (&self->shapes); i++)
|
||||
{
|
||||
ottie_shape_snapshot (ottie_shape_list_get (&self->shapes, i),
|
||||
snapshot,
|
||||
&group_snapshot,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
ottie_shape_snapshot_clear (&group_snapshot);
|
||||
|
||||
gtk_snapshot_restore (snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_group_shape_dispose (GObject *object)
|
||||
{
|
||||
OttieGroupShape *self = OTTIE_GROUP_SHAPE (object);
|
||||
|
||||
ottie_shape_list_clear (&self->shapes);
|
||||
|
||||
G_OBJECT_CLASS (ottie_group_shape_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_group_shape_finalize (GObject *object)
|
||||
{
|
||||
//OttieGroupShape *self = OTTIE_GROUP_SHAPE (object);
|
||||
|
||||
G_OBJECT_CLASS (ottie_group_shape_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_group_shape_class_init (OttieGroupShapeClass *klass)
|
||||
{
|
||||
OttieShapeClass *shape_class = OTTIE_SHAPE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
shape_class->snapshot = ottie_group_shape_snapshot;
|
||||
|
||||
gobject_class->finalize = ottie_group_shape_finalize;
|
||||
gobject_class->dispose = ottie_group_shape_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_group_shape_init (OttieGroupShape *self)
|
||||
{
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_group_shape_parse_shapes (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttieGroupShape *self = data;
|
||||
|
||||
if (!json_reader_is_array (reader))
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "Shapes are not an array.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (int i = 0; ; i++)
|
||||
{
|
||||
OttieShape *shape;
|
||||
const char *type;
|
||||
|
||||
if (!json_reader_read_element (reader, i))
|
||||
break;
|
||||
|
||||
if (!json_reader_is_object (reader))
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "Shape %d is not an object", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!json_reader_read_member (reader, "ty"))
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "Shape %d has no type", i);
|
||||
json_reader_end_member (reader);
|
||||
json_reader_end_element (reader);
|
||||
continue;
|
||||
}
|
||||
|
||||
type = json_reader_get_string_value (reader);
|
||||
if (type == NULL || json_reader_get_error (reader))
|
||||
{
|
||||
ottie_parser_emit_error (reader, json_reader_get_error (reader));
|
||||
json_reader_end_member (reader);
|
||||
json_reader_end_element (reader);
|
||||
continue;
|
||||
}
|
||||
json_reader_end_member (reader);
|
||||
|
||||
if (g_str_equal (type, "fl"))
|
||||
shape = ottie_fill_shape_parse (reader);
|
||||
else if (g_str_equal (type, "gr"))
|
||||
shape = ottie_group_shape_parse (reader);
|
||||
else if (g_str_equal (type, "rc"))
|
||||
shape = ottie_rect_shape_parse (reader);
|
||||
else if (g_str_equal (type, "sh"))
|
||||
shape = ottie_path_shape_parse (reader);
|
||||
else if (g_str_equal (type, "st"))
|
||||
shape = ottie_stroke_shape_parse (reader);
|
||||
else if (g_str_equal (type, "tm"))
|
||||
shape = ottie_trim_shape_parse (reader);
|
||||
else if (g_str_equal (type, "tr"))
|
||||
shape = ottie_transform_parse (reader);
|
||||
else
|
||||
{
|
||||
ottie_parser_error_value (reader, "Shape %d has unknown type \"%s\"", i, type);
|
||||
shape = NULL;
|
||||
}
|
||||
|
||||
if (shape)
|
||||
ottie_shape_list_append (&self->shapes, shape);
|
||||
json_reader_end_element (reader);
|
||||
}
|
||||
|
||||
json_reader_end_element (reader);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
OttieShape *
|
||||
ottie_group_shape_new (void)
|
||||
{
|
||||
return g_object_new (OTTIE_TYPE_GROUP_SHAPE, NULL);
|
||||
}
|
||||
|
||||
OttieShape *
|
||||
ottie_group_shape_parse (JsonReader *reader)
|
||||
{
|
||||
OttieParserOption options[] = {
|
||||
OTTIE_PARSE_OPTIONS_SHAPE
|
||||
{ "bm", ottie_parser_option_blend_mode, G_STRUCT_OFFSET (OttieGroupShape, blend_mode) },
|
||||
{ "np", ottie_parser_option_skip_expression, 0 },
|
||||
{ "cix", ottie_parser_option_skip_index, 0 },
|
||||
{ "it", ottie_group_shape_parse_shapes, 0 },
|
||||
};
|
||||
OttieShape *self;
|
||||
|
||||
self = ottie_group_shape_new ();
|
||||
|
||||
if (!ottie_parser_parse_object (reader, "group shape", options, G_N_ELEMENTS (options), self))
|
||||
{
|
||||
g_object_unref (self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
50
ottie/ottiegroupshapeprivate.h
Normal file
50
ottie/ottiegroupshapeprivate.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_GROUP_SHAPE_PRIVATE_H__
|
||||
#define __OTTIE_GROUP_SHAPE_PRIVATE_H__
|
||||
|
||||
#include "ottieshapeprivate.h"
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OTTIE_TYPE_GROUP_SHAPE (ottie_group_shape_get_type ())
|
||||
#define OTTIE_GROUP_SHAPE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OTTIE_TYPE_GROUP_SHAPE, OttieGroupShape))
|
||||
#define OTTIE_GROUP_SHAPE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), OTTIE_TYPE_GROUP_SHAPE, OttieGroupShapeClass))
|
||||
#define OTTIE_IS_GROUP_SHAPE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OTTIE_TYPE_GROUP_SHAPE))
|
||||
#define OTTIE_IS_GROUP_SHAPE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OTTIE_TYPE_GROUP_SHAPE))
|
||||
#define OTTIE_GROUP_SHAPE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OTTIE_TYPE_GROUP_SHAPE, OttieGroupShapeClass))
|
||||
|
||||
typedef struct _OttieGroupShape OttieGroupShape;
|
||||
typedef struct _OttieGroupShapeClass OttieGroupShapeClass;
|
||||
|
||||
GType ottie_group_shape_get_type (void) G_GNUC_CONST;
|
||||
|
||||
OttieShape * ottie_group_shape_new (void);
|
||||
OttieShape * ottie_group_shape_parse (JsonReader *reader);
|
||||
|
||||
gboolean ottie_group_shape_parse_shapes (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_GROUP_SHAPE_PRIVATE_H__ */
|
||||
382
ottie/ottiekeyframesimpl.c
Normal file
382
ottie/ottiekeyframesimpl.c
Normal file
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifndef OTTIE_KEYFRAMES_TYPE_NAME
|
||||
#define OTTIE_KEYFRAMES_TYPE_NAME OttieKeyframes
|
||||
#endif
|
||||
|
||||
#ifndef OTTIE_KEYFRAMES_NAME
|
||||
#define OTTIE_KEYFRAMES_NAME ottie_keyframes
|
||||
#endif
|
||||
|
||||
#ifndef OTTIE_KEYFRAMES_ELEMENT_TYPE
|
||||
#define OTTIE_KEYFRAMES_ELEMENT_TYPE gpointer
|
||||
#endif
|
||||
|
||||
#ifndef OTTIE_KEYFRAMES_DIMENSIONS
|
||||
#define OTTIE_KEYFRAMES_DIMENSIONS 1
|
||||
#endif
|
||||
|
||||
/* make this readable */
|
||||
#define _T_ OTTIE_KEYFRAMES_ELEMENT_TYPE
|
||||
#define OttieKeyframes OTTIE_KEYFRAMES_TYPE_NAME
|
||||
#define OttieKeyframe OTTIE_KEYFRAMES_TYPE_NAME ## Keyframe
|
||||
#define OttieControlPoint OTTIE_KEYFRAMES_TYPE_NAME ## ControlPoint
|
||||
#define ottie_keyframes_paste_more(OTTIE_KEYFRAMES_NAME, func_name) OTTIE_KEYFRAMES_NAME ## _ ## func_name
|
||||
#define ottie_keyframes_paste(OTTIE_KEYFRAMES_NAME, func_name) ottie_keyframes_paste_more (OTTIE_KEYFRAMES_NAME, func_name)
|
||||
#define ottie_keyframes(func_name) ottie_keyframes_paste (OTTIE_KEYFRAMES_NAME, func_name)
|
||||
|
||||
typedef struct OttieControlPoint OttieControlPoint;
|
||||
typedef struct OttieKeyframe OttieKeyframe;
|
||||
typedef struct OttieKeyframes OttieKeyframes;
|
||||
|
||||
struct OttieControlPoint
|
||||
{
|
||||
double x[OTTIE_KEYFRAMES_DIMENSIONS];
|
||||
double y[OTTIE_KEYFRAMES_DIMENSIONS];
|
||||
};
|
||||
|
||||
struct OttieKeyframe
|
||||
{
|
||||
/* Cubic control points, but Lottie names them in and out points */
|
||||
OttieControlPoint in;
|
||||
OttieControlPoint out;
|
||||
double start_time;
|
||||
_T_ start_value;
|
||||
_T_ end_value;
|
||||
};
|
||||
|
||||
struct OttieKeyframes
|
||||
{
|
||||
gsize n_items;
|
||||
OttieKeyframe items[];
|
||||
};
|
||||
|
||||
static inline OttieKeyframes *
|
||||
ottie_keyframes(new) (gsize n_items)
|
||||
{
|
||||
OttieKeyframes *self;
|
||||
|
||||
self = g_malloc0 (sizeof (OttieKeyframes) + n_items * sizeof (OttieKeyframe));
|
||||
self->n_items = n_items;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ottie_keyframes(free_value) (_T_ *item)
|
||||
{
|
||||
#ifdef OTTIE_KEYFRAMES_FREE_FUNC
|
||||
#ifdef OTTIE_KEYFRAMES_BY_VALUE
|
||||
OTTIE_KEYFRAMES_FREE_FUNC (item);
|
||||
#else
|
||||
OTTIE_KEYFRAMES_FREE_FUNC (*item);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
ottie_keyframes(copy_value) (_T_ *dest,
|
||||
_T_ *src)
|
||||
{
|
||||
#ifdef OTTIE_KEYFRAMES_COPY_FUNC
|
||||
# ifdef OTTIE_KEYFRAMES_BY_VALUE
|
||||
OTTIE_KEYFRAMES_COPY_FUNC (dest, src);
|
||||
# else
|
||||
*dest = OTTIE_KEYFRAMES_COPY_FUNC (*src);
|
||||
# endif
|
||||
#else
|
||||
*dest = *src;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* no G_GNUC_UNUSED here */
|
||||
static inline void
|
||||
ottie_keyframes(free) (OttieKeyframes *self)
|
||||
{
|
||||
#ifdef OTTIE_KEYFRAMES_FREE_FUNC
|
||||
gsize i;
|
||||
|
||||
for (i = 0; i < self->n_items; i++)
|
||||
{
|
||||
ottie_keyframes(free_value) (&self->items[i].start_value);
|
||||
ottie_keyframes(free_value) (&self->items[i].end_value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static
|
||||
#ifdef OTTIE_KEYFRAMES_BY_VALUE
|
||||
void
|
||||
#else
|
||||
_T_
|
||||
#endif
|
||||
ottie_keyframes(get) (const OttieKeyframes *self,
|
||||
double timestamp
|
||||
#ifdef OTTIE_KEYFRAMES_BY_VALUE
|
||||
, _T_ *out_result
|
||||
#endif
|
||||
)
|
||||
{
|
||||
const OttieKeyframe *keyframe;
|
||||
gsize i;
|
||||
|
||||
for (i = 0; i < self->n_items; i++)
|
||||
{
|
||||
if (self->items[i].start_time > timestamp)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 0 || i >= self->n_items)
|
||||
{
|
||||
keyframe = &self->items[i == 0 ? 0 : self->n_items - 1];
|
||||
#ifdef OTTIE_KEYFRAMES_BY_VALUE
|
||||
*out_result = keyframe->start_value;
|
||||
return;
|
||||
#else
|
||||
return keyframe->start_value;
|
||||
#endif
|
||||
}
|
||||
|
||||
keyframe = &self->items[i - 1];
|
||||
|
||||
double progress = (timestamp - keyframe->start_time) / (self->items[i].start_time - keyframe->start_time);
|
||||
#ifdef OTTIE_KEYFRAMES_BY_VALUE
|
||||
OTTIE_KEYFRAMES_INTERPOLATE_FUNC (&keyframe->start_value, &keyframe->end_value, progress, out_result);
|
||||
#else
|
||||
return OTTIE_KEYFRAMES_INTERPOLATE_FUNC (keyframe->start_value, keyframe->end_value, progress);
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_keyframes(parse_control_point_dimension) (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
double d[OTTIE_KEYFRAMES_DIMENSIONS];
|
||||
|
||||
if (json_reader_is_array (reader))
|
||||
{
|
||||
if (json_reader_count_elements (reader) != OTTIE_KEYFRAMES_DIMENSIONS)
|
||||
ottie_parser_error_value (reader, "control point has %d dimension, not %u", json_reader_count_elements (reader), OTTIE_KEYFRAMES_DIMENSIONS);
|
||||
|
||||
for (int i = 0; i < OTTIE_KEYFRAMES_DIMENSIONS; i++)
|
||||
{
|
||||
if (!json_reader_read_element (reader, i))
|
||||
{
|
||||
ottie_parser_emit_error (reader, json_reader_get_error (reader));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ottie_parser_option_double (reader, 0, &d[i]))
|
||||
d[i] = 0;
|
||||
}
|
||||
json_reader_end_element (reader);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ottie_parser_option_double (reader, 0, &d[0]))
|
||||
return FALSE;
|
||||
|
||||
for (gsize i = 1; i < OTTIE_KEYFRAMES_DIMENSIONS; i++)
|
||||
d[i] = d[0];
|
||||
}
|
||||
|
||||
memcpy ((guint8 *) data + GPOINTER_TO_SIZE (offset), d, sizeof (double) * OTTIE_KEYFRAMES_DIMENSIONS);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_keyframes(parse_control_point) (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttieParserOption options[] = {
|
||||
{ "x", ottie_keyframes(parse_control_point_dimension), G_STRUCT_OFFSET (OttieControlPoint, x) },
|
||||
{ "y", ottie_keyframes(parse_control_point_dimension), G_STRUCT_OFFSET (OttieControlPoint, y) },
|
||||
};
|
||||
OttieControlPoint cp;
|
||||
OttieControlPoint *target = (OttieControlPoint *) ((guint8 *) data + offset);
|
||||
|
||||
if (!ottie_parser_parse_object (reader, "control point", options, G_N_ELEMENTS (options), &cp))
|
||||
return FALSE;
|
||||
|
||||
*target = cp;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
OttieKeyframe keyframe;
|
||||
gboolean has_start_value;
|
||||
gboolean has_end_value;
|
||||
} OttieKeyframeParse;
|
||||
|
||||
static gboolean
|
||||
ottie_keyframes(parse_start_value) (JsonReader *reader,
|
||||
gsize pos,
|
||||
gpointer data)
|
||||
{
|
||||
OttieKeyframeParse *parse = data;
|
||||
|
||||
if (parse->has_start_value)
|
||||
ottie_keyframes(free_value) (&parse->keyframe.start_value);
|
||||
|
||||
parse->has_start_value = OTTIE_KEYFRAMES_PARSE_FUNC (reader, 0, &parse->keyframe.start_value);
|
||||
return parse->has_start_value;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_keyframes(parse_end_value) (JsonReader *reader,
|
||||
gsize pos,
|
||||
gpointer data)
|
||||
{
|
||||
OttieKeyframeParse *parse = data;
|
||||
|
||||
if (parse->has_end_value)
|
||||
ottie_keyframes(free_value) (&parse->keyframe.end_value);
|
||||
|
||||
parse->has_end_value = OTTIE_KEYFRAMES_PARSE_FUNC (reader, 0, &parse->keyframe.end_value);
|
||||
return parse->has_end_value;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
OttieKeyframes *keyframes;
|
||||
gboolean has_end_value;
|
||||
} OttieKeyframesParse;
|
||||
|
||||
static gboolean
|
||||
ottie_keyframes(parse_keyframe) (JsonReader *reader,
|
||||
gsize pos,
|
||||
gpointer data)
|
||||
{
|
||||
OttieParserOption options[] = {
|
||||
{ "s", ottie_keyframes(parse_start_value), 0, },
|
||||
{ "e", ottie_keyframes(parse_end_value), 0, },
|
||||
{ "t", ottie_parser_option_double, G_STRUCT_OFFSET (OttieKeyframe, start_time) },
|
||||
{ "i", ottie_keyframes(parse_control_point), G_STRUCT_OFFSET (OttieKeyframe, in) },
|
||||
{ "o", ottie_keyframes(parse_control_point), G_STRUCT_OFFSET (OttieKeyframe, out) },
|
||||
{ "ix", ottie_parser_option_skip_index, 0 },
|
||||
};
|
||||
OttieKeyframesParse *self = data;
|
||||
OttieKeyframeParse parse = { 0, };
|
||||
|
||||
if (!ottie_parser_parse_object (reader, "keyframe", options, G_N_ELEMENTS (options), &parse))
|
||||
goto fail;
|
||||
|
||||
if (pos == 0)
|
||||
{
|
||||
if (!parse.has_start_value)
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "First keyframe must have a start value");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parse.keyframe.start_time <= self->keyframes->items[pos - 1].start_time)
|
||||
goto fail;
|
||||
|
||||
if (!parse.has_start_value)
|
||||
{
|
||||
if (self->has_end_value)
|
||||
{
|
||||
ottie_keyframes(copy_value) (&parse.keyframe.start_value, &self->keyframes->items[pos - 1].end_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "Keyframe %zu has no end value and %zu has no start value.", pos - 1, pos);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!self->has_end_value)
|
||||
ottie_keyframes(copy_value) (&self->keyframes->items[pos - 1].end_value, &parse.keyframe.start_value);
|
||||
}
|
||||
|
||||
self->has_end_value = parse.has_end_value;
|
||||
self->keyframes->items[pos] = parse.keyframe;
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
self->keyframes->n_items = pos;
|
||||
if (parse.has_start_value)
|
||||
ottie_keyframes(free_value) (&parse.keyframe.start_value);
|
||||
if (parse.has_end_value)
|
||||
ottie_keyframes(free_value) (&parse.keyframe.end_value);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* no G_GNUC_UNUSED here, if you don't use a type, remove it. */
|
||||
static inline OttieKeyframes *
|
||||
ottie_keyframes(parse) (JsonReader *reader)
|
||||
{
|
||||
OttieKeyframesParse parse;
|
||||
OttieKeyframes *self;
|
||||
|
||||
self = ottie_keyframes(new) (json_reader_count_elements (reader));
|
||||
|
||||
parse.keyframes = self;
|
||||
parse.has_end_value = FALSE;
|
||||
|
||||
if (!ottie_parser_parse_array (reader, "keyframes",
|
||||
self->n_items, self->n_items,
|
||||
NULL,
|
||||
0, 1,
|
||||
ottie_keyframes(parse_keyframe),
|
||||
&parse))
|
||||
{
|
||||
/* do a dumb copy so the free has something to free */
|
||||
if (!parse.has_end_value && self->n_items > 0)
|
||||
ottie_keyframes(copy_value) (&self->items[self->n_items - 1].end_value,
|
||||
&self->items[self->n_items - 1].start_value);
|
||||
ottie_keyframes(free) (self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!parse.has_end_value)
|
||||
ottie_keyframes(copy_value) (&self->items[self->n_items - 1].end_value,
|
||||
&self->items[self->n_items - 1].start_value);
|
||||
|
||||
return parse.keyframes;
|
||||
}
|
||||
|
||||
#ifndef OTTIE_KEYFRAMES_NO_UNDEF
|
||||
|
||||
#undef _T_
|
||||
#undef OttieKeyframes
|
||||
#undef ottie_keyframes_paste_more
|
||||
#undef ottie_keyframes_paste
|
||||
#undef ottie_keyframes
|
||||
|
||||
#undef OTTIE_KEYFRAMES_COPY_FUNC
|
||||
#undef OTTIE_KEYFRAMES_PARSE_FUNC
|
||||
#undef OTTIE_KEYFRAMES_BY_VALUE
|
||||
#undef OTTIE_KEYFRAMES_ELEMENT_TYPE
|
||||
#undef OTTIE_KEYFRAMES_FREE_FUNC
|
||||
#undef OTTIE_KEYFRAMES_NAME
|
||||
#undef OTTIE_KEYFRAMES_TYPE_NAME
|
||||
#endif
|
||||
79
ottie/ottielayer.c
Normal file
79
ottie/ottielayer.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottielayerprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
G_DEFINE_TYPE (OttieLayer, ottie_layer, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
ottie_layer_dispose (GObject *object)
|
||||
{
|
||||
OttieLayer *self = OTTIE_LAYER (object);
|
||||
|
||||
g_clear_object (&self->transform);
|
||||
|
||||
G_OBJECT_CLASS (ottie_layer_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_layer_finalize (GObject *object)
|
||||
{
|
||||
//OttieLayer *self = OTTIE_LAYER (object);
|
||||
|
||||
G_OBJECT_CLASS (ottie_layer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_layer_class_init (OttieLayerClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
|
||||
gobject_class->finalize = ottie_layer_finalize;
|
||||
gobject_class->dispose = ottie_layer_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_layer_init (OttieLayer *self)
|
||||
{
|
||||
self->stretch = 1;
|
||||
self->blend_mode = GSK_BLEND_MODE_DEFAULT;
|
||||
}
|
||||
|
||||
void
|
||||
ottie_layer_snapshot (OttieLayer *self,
|
||||
GtkSnapshot *snapshot,
|
||||
double timestamp)
|
||||
{
|
||||
if (self->transform)
|
||||
{
|
||||
GskTransform *transform;
|
||||
|
||||
transform = ottie_transform_get_transform (self->transform, timestamp);
|
||||
gtk_snapshot_transform (snapshot, transform);
|
||||
gsk_transform_unref (transform);
|
||||
}
|
||||
|
||||
OTTIE_LAYER_GET_CLASS (self)->snapshot (self, snapshot, timestamp);
|
||||
}
|
||||
|
||||
88
ottie/ottielayerprivate.h
Normal file
88
ottie/ottielayerprivate.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_LAYER_PRIVATE_H__
|
||||
#define __OTTIE_LAYER_PRIVATE_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "ottie/ottietransformprivate.h"
|
||||
#include "ottie/ottieparserprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OTTIE_TYPE_LAYER (ottie_layer_get_type ())
|
||||
#define OTTIE_LAYER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OTTIE_TYPE_LAYER, OttieLayer))
|
||||
#define OTTIE_LAYER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), OTTIE_TYPE_LAYER, OttieLayerClass))
|
||||
#define OTTIE_IS_LAYER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OTTIE_TYPE_LAYER))
|
||||
#define OTTIE_IS_LAYER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OTTIE_TYPE_LAYER))
|
||||
#define OTTIE_LAYER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OTTIE_TYPE_LAYER, OttieLayerClass))
|
||||
|
||||
typedef struct _OttieLayer OttieLayer;
|
||||
typedef struct _OttieLayerClass OttieLayerClass;
|
||||
|
||||
struct _OttieLayer
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
OttieTransform *transform;
|
||||
gboolean auto_orient;
|
||||
GskBlendMode blend_mode;
|
||||
double index;
|
||||
char *layer_name;
|
||||
char *name;
|
||||
double start_frame;
|
||||
double end_frame;
|
||||
double start_time;
|
||||
double stretch;
|
||||
};
|
||||
|
||||
struct _OttieLayerClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* snapshot) (OttieLayer *layer,
|
||||
GtkSnapshot *snapshot,
|
||||
double timestamp);
|
||||
};
|
||||
|
||||
GType ottie_layer_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void ottie_layer_snapshot (OttieLayer *self,
|
||||
GtkSnapshot *snapshot,
|
||||
double timestamp);
|
||||
|
||||
#define OTTIE_PARSE_OPTIONS_LAYER \
|
||||
{ "ao", ottie_parser_option_boolean, G_STRUCT_OFFSET (OttieLayer, auto_orient) }, \
|
||||
{ "bm", ottie_parser_option_blend_mode, G_STRUCT_OFFSET (OttieLayer, blend_mode) }, \
|
||||
{ "nm", ottie_parser_option_string, G_STRUCT_OFFSET (OttieLayer, name) }, \
|
||||
{ "ln", ottie_parser_option_string, G_STRUCT_OFFSET (OttieLayer, layer_name) }, \
|
||||
{ "ks", ottie_parser_option_transform, G_STRUCT_OFFSET (OttieLayer, transform) }, \
|
||||
{ "ip", ottie_parser_option_double, G_STRUCT_OFFSET (OttieLayer, start_frame) }, \
|
||||
{ "ind", ottie_parser_option_double, G_STRUCT_OFFSET (OttieLayer, index) }, \
|
||||
{ "op", ottie_parser_option_double, G_STRUCT_OFFSET (OttieLayer, end_frame) }, \
|
||||
{ "st", ottie_parser_option_double, G_STRUCT_OFFSET (OttieLayer, start_time) }, \
|
||||
{ "sr", ottie_parser_option_double, G_STRUCT_OFFSET (OttieLayer, stretch) }, \
|
||||
{ "ddd", ottie_parser_option_3d, 0 }, \
|
||||
{ "ix", ottie_parser_option_skip_index, 0 }, \
|
||||
{ "ty", ottie_parser_option_skip, 0 },
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_LAYER_PRIVATE_H__ */
|
||||
381
ottie/ottiepaintable.c
Normal file
381
ottie/ottiepaintable.c
Normal file
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottiepaintable.h"
|
||||
|
||||
#include "ottiecreationprivate.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
struct _OttiePaintable
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
OttieCreation *creation;
|
||||
gint64 timestamp;
|
||||
};
|
||||
|
||||
struct _OttiePaintableClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_CREATION,
|
||||
PROP_DURATION,
|
||||
PROP_TIMESTAMP,
|
||||
|
||||
N_PROPS,
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
ottie_paintable_paintable_snapshot (GdkPaintable *paintable,
|
||||
GdkSnapshot *snapshot,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
OttiePaintable *self = OTTIE_PAINTABLE (paintable);
|
||||
double w, h, timestamp;
|
||||
|
||||
if (!self->creation)
|
||||
return;
|
||||
|
||||
w = ottie_creation_get_width (self->creation);
|
||||
h = ottie_creation_get_height (self->creation);
|
||||
timestamp = (double) self->timestamp / G_USEC_PER_SEC;
|
||||
|
||||
if (w != width || h != height)
|
||||
{
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_scale (snapshot, width / w, height / h);
|
||||
}
|
||||
|
||||
gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (0, 0, w, h));
|
||||
ottie_creation_snapshot (self->creation, snapshot, timestamp);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
|
||||
if (w != width || h != height)
|
||||
gtk_snapshot_restore (snapshot);
|
||||
}
|
||||
|
||||
static int
|
||||
ottie_paintable_paintable_get_intrinsic_width (GdkPaintable *paintable)
|
||||
{
|
||||
OttiePaintable *self = OTTIE_PAINTABLE (paintable);
|
||||
|
||||
if (!self->creation)
|
||||
return 0;
|
||||
|
||||
return ceil (ottie_creation_get_width (self->creation));
|
||||
}
|
||||
|
||||
static int
|
||||
ottie_paintable_paintable_get_intrinsic_height (GdkPaintable *paintable)
|
||||
{
|
||||
OttiePaintable *self = OTTIE_PAINTABLE (paintable);
|
||||
|
||||
if (!self->creation)
|
||||
return 0;
|
||||
|
||||
return ceil (ottie_creation_get_height (self->creation));
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_paintable_paintable_init (GdkPaintableInterface *iface)
|
||||
{
|
||||
iface->snapshot = ottie_paintable_paintable_snapshot;
|
||||
iface->get_intrinsic_width = ottie_paintable_paintable_get_intrinsic_width;
|
||||
iface->get_intrinsic_height = ottie_paintable_paintable_get_intrinsic_height;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (OttiePaintable, ottie_paintable, G_TYPE_OBJECT, 0,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||
ottie_paintable_paintable_init))
|
||||
|
||||
static void
|
||||
ottie_paintable_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
|
||||
{
|
||||
OttiePaintable *self = OTTIE_PAINTABLE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CREATION:
|
||||
ottie_paintable_set_creation (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_TIMESTAMP:
|
||||
ottie_paintable_set_timestamp (self, g_value_get_int64 (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_paintable_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
OttiePaintable *self = OTTIE_PAINTABLE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CREATION:
|
||||
g_value_set_object (value, self->creation);
|
||||
break;
|
||||
|
||||
case PROP_DURATION:
|
||||
g_value_set_int64 (value, ottie_paintable_get_duration (self));
|
||||
break;
|
||||
|
||||
case PROP_TIMESTAMP:
|
||||
g_value_set_int64 (value, self->timestamp);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_paintable_prepared_cb (OttieCreation *creation,
|
||||
GParamSpec *pspec,
|
||||
OttiePaintable *self)
|
||||
{
|
||||
gdk_paintable_invalidate_size (GDK_PAINTABLE (self));
|
||||
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DURATION]);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_paintable_unset_creation (OttiePaintable *self)
|
||||
{
|
||||
if (self->creation == NULL)
|
||||
return;
|
||||
|
||||
g_signal_handlers_disconnect_by_func (self->creation, ottie_paintable_prepared_cb, self);
|
||||
g_clear_object (&self->creation);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_paintable_dispose (GObject *object)
|
||||
{
|
||||
OttiePaintable *self = OTTIE_PAINTABLE (object);
|
||||
|
||||
ottie_paintable_unset_creation (self);
|
||||
|
||||
G_OBJECT_CLASS (ottie_paintable_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_paintable_class_init (OttiePaintableClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->get_property = ottie_paintable_get_property;
|
||||
gobject_class->set_property = ottie_paintable_set_property;
|
||||
gobject_class->dispose = ottie_paintable_dispose;
|
||||
|
||||
/**
|
||||
* OttiePaintable:creation
|
||||
*
|
||||
* The displayed creation or %NULL.
|
||||
*/
|
||||
properties[PROP_CREATION] =
|
||||
g_param_spec_object ("creation",
|
||||
_("Creation"),
|
||||
_("The displayed creation"),
|
||||
OTTIE_TYPE_CREATION,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* OttiePaintable:duration
|
||||
*
|
||||
* Duration of the displayed creation
|
||||
*/
|
||||
properties[PROP_DURATION] =
|
||||
g_param_spec_int64 ("duration",
|
||||
_("Duration"),
|
||||
_("Duration of the displayed creation"),
|
||||
0, G_MAXINT64, 0,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* OttiePaintable:timestamp
|
||||
*
|
||||
* At what timestamp to display the creation.
|
||||
*/
|
||||
properties[PROP_TIMESTAMP] =
|
||||
g_param_spec_int64 ("timestmp",
|
||||
_("Timestamp"),
|
||||
_("At what timestamp to display the creation"),
|
||||
0, G_MAXINT64, 0,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_paintable_init (OttiePaintable *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_paintable_new:
|
||||
* @creation: (allow-none) (transfer full): an #OttiePaintable or %NULL
|
||||
*
|
||||
* Creates a new Ottie paintable for the given @creation
|
||||
*
|
||||
* Returns: (transfer full) (type OttiePaintable): a new #OttiePaintable
|
||||
**/
|
||||
OttiePaintable *
|
||||
ottie_paintable_new (OttieCreation *creation)
|
||||
{
|
||||
OttiePaintable *self;
|
||||
|
||||
g_return_val_if_fail (creation == creation || OTTIE_IS_CREATION (creation), NULL);
|
||||
|
||||
self = g_object_new (OTTIE_TYPE_PAINTABLE,
|
||||
"creation", creation,
|
||||
NULL);
|
||||
|
||||
g_clear_object (&creation);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_paintable_get_creation:
|
||||
* @self: an #OttiePaintable
|
||||
*
|
||||
* Returns the creation that shown or %NULL
|
||||
* if none.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): the observed creation.
|
||||
**/
|
||||
OttieCreation *
|
||||
ottie_paintable_get_creation (OttiePaintable *self)
|
||||
{
|
||||
g_return_val_if_fail (OTTIE_IS_PAINTABLE (self), NULL);
|
||||
|
||||
return self->creation;
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_paintable_set_creation:
|
||||
* @self: an #OttiePaintable
|
||||
* @creation: (allow-none): the creation to show or %NULL
|
||||
*
|
||||
* Sets the creation that should be shown.
|
||||
**/
|
||||
void
|
||||
ottie_paintable_set_creation (OttiePaintable *self,
|
||||
OttieCreation *creation)
|
||||
{
|
||||
g_return_if_fail (OTTIE_IS_PAINTABLE (self));
|
||||
g_return_if_fail (creation == NULL || OTTIE_IS_CREATION (creation));
|
||||
|
||||
if (self->creation == creation)
|
||||
return;
|
||||
|
||||
ottie_paintable_unset_creation (self);
|
||||
|
||||
self->creation = g_object_ref (creation);
|
||||
g_signal_connect (creation, "notify::prepared", G_CALLBACK (ottie_paintable_prepared_cb), self);
|
||||
|
||||
gdk_paintable_invalidate_size (GDK_PAINTABLE (self));
|
||||
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CREATION]);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DURATION]);
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_paintable_get_timestamp:
|
||||
* @self: an #OttiePaintable
|
||||
*
|
||||
* Gets the timestamp for the currently displayed image.
|
||||
*
|
||||
* Returns: the timestamp
|
||||
**/
|
||||
gint64
|
||||
ottie_paintable_get_timestamp (OttiePaintable *self)
|
||||
{
|
||||
g_return_val_if_fail (OTTIE_IS_PAINTABLE (self), 0);
|
||||
|
||||
return self->timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_paintable_set_timestamp:
|
||||
* @self: an #OttiePaintable
|
||||
* @timestamp: the timestamp to display
|
||||
*
|
||||
* Sets the timestamp to display the creation at.
|
||||
**/
|
||||
void
|
||||
ottie_paintable_set_timestamp (OttiePaintable *self,
|
||||
gint64 timestamp)
|
||||
{
|
||||
g_return_if_fail (OTTIE_IS_PAINTABLE (self));
|
||||
g_return_if_fail (timestamp >= 0);
|
||||
|
||||
if (self->timestamp == timestamp)
|
||||
return;
|
||||
|
||||
self->timestamp = timestamp;
|
||||
|
||||
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TIMESTAMP]);
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_paintable_get_duration:
|
||||
* @self: an #OttiePaintable
|
||||
*
|
||||
* Gets the duration of the currently playing creation.
|
||||
*
|
||||
* Returns: The duration in usec.
|
||||
**/
|
||||
gint64
|
||||
ottie_paintable_get_duration (OttiePaintable *self)
|
||||
{
|
||||
g_return_val_if_fail (OTTIE_IS_PAINTABLE (self), 0);
|
||||
|
||||
if (self->creation == NULL)
|
||||
return 0;
|
||||
|
||||
return ceil (G_USEC_PER_SEC * ottie_creation_get_end_frame (self->creation)
|
||||
/ ottie_creation_get_frame_rate (self->creation));
|
||||
}
|
||||
|
||||
54
ottie/ottiepaintable.h
Normal file
54
ottie/ottiepaintable.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_PAINTABLE_H__
|
||||
#define __OTTIE_PAINTABLE_H__
|
||||
|
||||
#if !defined (__OTTIE_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <ottie/ottie.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <ottie/ottiecreation.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OTTIE_TYPE_PAINTABLE (ottie_paintable_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (OttiePaintable, ottie_paintable, OTTIE, PAINTABLE, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
OttiePaintable * ottie_paintable_new (OttieCreation *creation);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
OttieCreation * ottie_paintable_get_creation (OttiePaintable *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void ottie_paintable_set_creation (OttiePaintable *self,
|
||||
OttieCreation *creation);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gint64 ottie_paintable_get_timestamp (OttiePaintable *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void ottie_paintable_set_timestamp (OttiePaintable *self,
|
||||
gint64 timestamp);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gint64 ottie_paintable_get_duration (OttiePaintable *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_PAINTABLE_H__ */
|
||||
490
ottie/ottieparser.c
Normal file
490
ottie/ottieparser.c
Normal file
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottieparserprivate.h"
|
||||
|
||||
#include "ottietransformprivate.h"
|
||||
|
||||
#include <gsk/gsk.h>
|
||||
|
||||
void
|
||||
ottie_parser_emit_error (JsonReader *reader,
|
||||
const GError *error)
|
||||
{
|
||||
g_printerr ("Ottie is sad: %s\n", error->message);
|
||||
}
|
||||
|
||||
void
|
||||
ottie_parser_error_syntax (JsonReader *reader,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
GError *error;
|
||||
|
||||
va_start (args, format);
|
||||
error = g_error_new_valist (JSON_PARSER_ERROR,
|
||||
JSON_PARSER_ERROR_INVALID_DATA,
|
||||
format, args);
|
||||
va_end (args);
|
||||
|
||||
ottie_parser_emit_error (reader, error);
|
||||
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
void
|
||||
ottie_parser_error_value (JsonReader *reader,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
GError *error;
|
||||
|
||||
va_start (args, format);
|
||||
error = g_error_new_valist (JSON_PARSER_ERROR,
|
||||
JSON_PARSER_ERROR_INVALID_DATA,
|
||||
format, args);
|
||||
va_end (args);
|
||||
|
||||
ottie_parser_emit_error (reader, error);
|
||||
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
void
|
||||
ottie_parser_error_unsupported (JsonReader *reader,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
GError *error;
|
||||
|
||||
va_start (args, format);
|
||||
error = g_error_new_valist (JSON_PARSER_ERROR,
|
||||
JSON_PARSER_ERROR_INVALID_DATA,
|
||||
format, args);
|
||||
va_end (args);
|
||||
|
||||
ottie_parser_emit_error (reader, error);
|
||||
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_parser_parse_array (JsonReader *reader,
|
||||
const char *debug_name,
|
||||
guint min_items,
|
||||
guint max_items,
|
||||
guint *out_n_items,
|
||||
gsize start_offset,
|
||||
gsize offset_multiplier,
|
||||
OttieParseFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!json_reader_is_array (reader))
|
||||
{
|
||||
if (min_items > 1)
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "Expected an array when parsing %s", debug_name);
|
||||
if (out_n_items)
|
||||
*out_n_items = 0;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!func (reader, start_offset, data))
|
||||
{
|
||||
if (out_n_items)
|
||||
*out_n_items = 0;
|
||||
return FALSE;
|
||||
}
|
||||
if (out_n_items)
|
||||
*out_n_items = 1;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (json_reader_count_elements (reader) < min_items)
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "%s needs %u items, but only %u given",
|
||||
debug_name, min_items, json_reader_count_elements (reader));
|
||||
return FALSE;
|
||||
}
|
||||
max_items = MIN (max_items, json_reader_count_elements (reader));
|
||||
|
||||
for (i = 0; i < max_items; i++)
|
||||
{
|
||||
if (!json_reader_read_element (reader, i) ||
|
||||
!func (reader, start_offset + offset_multiplier * i, data))
|
||||
{
|
||||
json_reader_end_element (reader);
|
||||
if (out_n_items)
|
||||
*out_n_items = i;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
json_reader_end_element (reader);
|
||||
}
|
||||
|
||||
if (out_n_items)
|
||||
*out_n_items = i;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_parser_parse_object (JsonReader *reader,
|
||||
const char *debug_name,
|
||||
const OttieParserOption *options,
|
||||
gsize n_options,
|
||||
gpointer data)
|
||||
{
|
||||
if (!json_reader_is_object (reader))
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "Expected an object when parsing %s", debug_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (int i = 0; ; i++)
|
||||
{
|
||||
const OttieParserOption *o = NULL;
|
||||
const char *name;
|
||||
|
||||
if (!json_reader_read_element (reader, i))
|
||||
break;
|
||||
|
||||
name = json_reader_get_member_name (reader);
|
||||
|
||||
for (gsize j = 0; j < n_options; j++)
|
||||
{
|
||||
o = &options[j];
|
||||
if (g_str_equal (o->name, name))
|
||||
break;
|
||||
o = NULL;
|
||||
}
|
||||
|
||||
if (o)
|
||||
{
|
||||
if (!o->parse_func (reader, o->option_data, data))
|
||||
{
|
||||
json_reader_end_element (reader);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ottie_parser_error_unsupported (reader, "Unsupported %s property \"%s\"", debug_name, json_reader_get_member_name (reader));
|
||||
}
|
||||
|
||||
json_reader_end_element (reader);
|
||||
}
|
||||
|
||||
json_reader_end_element (reader);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_parser_option_skip (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_parser_option_boolean (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
gboolean b;
|
||||
|
||||
b = json_reader_get_boolean_value (reader);
|
||||
if (json_reader_get_error (reader))
|
||||
{
|
||||
ottie_parser_emit_error (reader, json_reader_get_error (reader));
|
||||
json_reader_end_element (reader);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*(gboolean *) ((guint8 *) data + offset) = b;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_parser_option_double (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
double d;
|
||||
|
||||
d = json_reader_get_double_value (reader);
|
||||
if (json_reader_get_error (reader))
|
||||
{
|
||||
ottie_parser_emit_error (reader, json_reader_get_error (reader));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*(double *) ((guint8 *) data + offset) = d;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_parser_option_string (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
char **target;
|
||||
const char *s;
|
||||
|
||||
s = json_reader_get_string_value (reader);
|
||||
if (json_reader_get_error (reader))
|
||||
{
|
||||
ottie_parser_emit_error (reader, json_reader_get_error (reader));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
target = (char **) ((guint8 *) data + offset);
|
||||
|
||||
g_clear_pointer (target, g_free);
|
||||
*target = g_strdup (s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_parser_option_blend_mode (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
GskBlendMode blend_mode;
|
||||
gint64 i;
|
||||
|
||||
i = json_reader_get_int_value (reader);
|
||||
if (json_reader_get_error (reader))
|
||||
{
|
||||
ottie_parser_emit_error (reader, json_reader_get_error (reader));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
blend_mode = GSK_BLEND_MODE_DEFAULT;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
blend_mode = GSK_BLEND_MODE_MULTIPLY;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
blend_mode = GSK_BLEND_MODE_SCREEN;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
blend_mode = GSK_BLEND_MODE_OVERLAY;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
blend_mode = GSK_BLEND_MODE_DARKEN;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
blend_mode = GSK_BLEND_MODE_LIGHTEN;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
blend_mode = GSK_BLEND_MODE_COLOR_DODGE;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
blend_mode = GSK_BLEND_MODE_COLOR_BURN;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
blend_mode = GSK_BLEND_MODE_HARD_LIGHT;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
blend_mode = GSK_BLEND_MODE_SOFT_LIGHT;
|
||||
break;
|
||||
|
||||
case 10:
|
||||
blend_mode = GSK_BLEND_MODE_DIFFERENCE;
|
||||
break;
|
||||
|
||||
case 11:
|
||||
blend_mode = GSK_BLEND_MODE_EXCLUSION;
|
||||
break;
|
||||
|
||||
case 12:
|
||||
blend_mode = GSK_BLEND_MODE_HUE;
|
||||
break;
|
||||
|
||||
case 13:
|
||||
blend_mode = GSK_BLEND_MODE_SATURATION;
|
||||
break;
|
||||
|
||||
case 14:
|
||||
blend_mode = GSK_BLEND_MODE_COLOR;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
blend_mode = GSK_BLEND_MODE_LUMINOSITY;
|
||||
break;
|
||||
|
||||
default:
|
||||
ottie_parser_error_value (reader, "%"G_GINT64_FORMAT" is not a known blend mode", i);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (blend_mode != GSK_BLEND_MODE_DEFAULT)
|
||||
ottie_parser_error_value (reader, "Blend modes are not implemented yet.");
|
||||
|
||||
*(GskBlendMode *) ((guint8 *) data + offset) = blend_mode;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_parser_option_3d (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
double d;
|
||||
|
||||
d = json_reader_get_double_value (reader);
|
||||
if (json_reader_get_error (reader))
|
||||
{
|
||||
ottie_parser_emit_error (reader, json_reader_get_error (reader));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (d != 0)
|
||||
{
|
||||
ottie_parser_error_value (reader, "3D is not supported.\n");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_parser_option_line_cap (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
GskLineCap line_cap;
|
||||
gint64 i;
|
||||
|
||||
i = json_reader_get_int_value (reader);
|
||||
if (json_reader_get_error (reader))
|
||||
{
|
||||
ottie_parser_emit_error (reader, json_reader_get_error (reader));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
line_cap = GSK_LINE_CAP_BUTT;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
line_cap = GSK_LINE_CAP_ROUND;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
line_cap = GSK_LINE_CAP_SQUARE;
|
||||
break;
|
||||
|
||||
default:
|
||||
ottie_parser_error_value (reader, "%"G_GINT64_FORMAT" is not a known line cap", i);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*(GskLineCap *) ((guint8 *) data + offset) = line_cap;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_parser_option_line_join (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
GskLineJoin line_join;
|
||||
gint64 i;
|
||||
|
||||
i = json_reader_get_int_value (reader);
|
||||
if (json_reader_get_error (reader))
|
||||
{
|
||||
ottie_parser_emit_error (reader, json_reader_get_error (reader));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
line_join = GSK_LINE_JOIN_MITER;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
line_join = GSK_LINE_JOIN_ROUND;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
line_join = GSK_LINE_JOIN_BEVEL;
|
||||
break;
|
||||
|
||||
default:
|
||||
ottie_parser_error_value (reader, "%"G_GINT64_FORMAT" is not a known line join", i);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*(GskLineJoin *) ((guint8 *) data + offset) = line_join;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_parser_option_transform (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttieShape **target;
|
||||
OttieShape *t;
|
||||
|
||||
t = ottie_transform_parse (reader);
|
||||
if (t == NULL)
|
||||
return FALSE;
|
||||
|
||||
target = (OttieShape **) ((guint8 *) data + offset);
|
||||
|
||||
g_clear_object (target);
|
||||
*target = t;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
97
ottie/ottieparserprivate.h
Normal file
97
ottie/ottieparserprivate.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_PARSER_PRIVATE_H__
|
||||
#define __OTTIE_PARSER_PRIVATE_H__
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _OttieParserOption OttieParserOption;
|
||||
|
||||
typedef gboolean (* OttieParseFunc) (JsonReader *reader, gsize offset, gpointer data);
|
||||
|
||||
struct _OttieParserOption
|
||||
{
|
||||
const char *name;
|
||||
OttieParseFunc parse_func;
|
||||
gsize option_data;
|
||||
};
|
||||
|
||||
void ottie_parser_emit_error (JsonReader *reader,
|
||||
const GError *error);
|
||||
void ottie_parser_error_syntax (JsonReader *reader,
|
||||
const char *format,
|
||||
...) G_GNUC_PRINTF (2, 3);
|
||||
void ottie_parser_error_value (JsonReader *reader,
|
||||
const char *format,
|
||||
...) G_GNUC_PRINTF (2, 3);
|
||||
void ottie_parser_error_unsupported (JsonReader *reader,
|
||||
const char *format,
|
||||
...) G_GNUC_PRINTF (2, 3);
|
||||
|
||||
gboolean ottie_parser_parse_array (JsonReader *reader,
|
||||
const char *debug_name,
|
||||
guint min_items,
|
||||
guint max_items,
|
||||
guint *out_n_items,
|
||||
gsize start_offset,
|
||||
gsize offset_multiplier,
|
||||
OttieParseFunc func,
|
||||
gpointer data);
|
||||
|
||||
gboolean ottie_parser_parse_object (JsonReader *reader,
|
||||
const char *debug_name,
|
||||
const OttieParserOption *options,
|
||||
gsize n_options,
|
||||
gpointer data);
|
||||
gboolean ottie_parser_option_skip (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
#define ottie_parser_option_skip_index ottie_parser_option_skip
|
||||
#define ottie_parser_option_skip_expression ottie_parser_option_skip
|
||||
gboolean ottie_parser_option_boolean (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
gboolean ottie_parser_option_double (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
gboolean ottie_parser_option_string (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
gboolean ottie_parser_option_3d (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
gboolean ottie_parser_option_blend_mode (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
gboolean ottie_parser_option_line_cap (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
gboolean ottie_parser_option_line_join (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
gboolean ottie_parser_option_transform (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_PARSER_PRIVATE_H__ */
|
||||
115
ottie/ottiepathshape.c
Normal file
115
ottie/ottiepathshape.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottiepathshapeprivate.h"
|
||||
|
||||
#include "ottiepathvalueprivate.h"
|
||||
#include "ottieparserprivate.h"
|
||||
#include "ottieshapeprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
struct _OttiePathShape
|
||||
{
|
||||
OttieShape parent;
|
||||
|
||||
double direction;
|
||||
OttiePathValue path;
|
||||
};
|
||||
|
||||
struct _OttiePathShapeClass
|
||||
{
|
||||
OttieShapeClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (OttiePathShape, ottie_path_shape, OTTIE_TYPE_SHAPE)
|
||||
|
||||
static void
|
||||
ottie_path_shape_snapshot (OttieShape *shape,
|
||||
GtkSnapshot *snapshot,
|
||||
OttieShapeSnapshot *snapshot_data,
|
||||
double timestamp)
|
||||
{
|
||||
OttiePathShape *self = OTTIE_PATH_SHAPE (shape);
|
||||
|
||||
ottie_shape_snapshot_add_path (snapshot_data,
|
||||
ottie_path_value_get (&self->path,
|
||||
timestamp,
|
||||
self->direction));
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_path_shape_dispose (GObject *object)
|
||||
{
|
||||
OttiePathShape *self = OTTIE_PATH_SHAPE (object);
|
||||
|
||||
ottie_path_value_clear (&self->path);
|
||||
|
||||
G_OBJECT_CLASS (ottie_path_shape_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_path_shape_finalize (GObject *object)
|
||||
{
|
||||
//OttiePathShape *self = OTTIE_PATH_SHAPE (object);
|
||||
|
||||
G_OBJECT_CLASS (ottie_path_shape_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_path_shape_class_init (OttiePathShapeClass *klass)
|
||||
{
|
||||
OttieShapeClass *shape_class = OTTIE_SHAPE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
shape_class->snapshot = ottie_path_shape_snapshot;
|
||||
|
||||
gobject_class->finalize = ottie_path_shape_finalize;
|
||||
gobject_class->dispose = ottie_path_shape_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_path_shape_init (OttiePathShape *self)
|
||||
{
|
||||
ottie_path_value_init (&self->path);
|
||||
}
|
||||
|
||||
OttieShape *
|
||||
ottie_path_shape_parse (JsonReader *reader)
|
||||
{
|
||||
OttieParserOption options[] = {
|
||||
OTTIE_PARSE_OPTIONS_SHAPE
|
||||
{ "d", ottie_parser_option_double, G_STRUCT_OFFSET (OttiePathShape, direction) },
|
||||
{ "ks", ottie_path_value_parse, G_STRUCT_OFFSET (OttiePathShape, path) },
|
||||
};
|
||||
OttiePathShape *self;
|
||||
|
||||
self = g_object_new (OTTIE_TYPE_PATH_SHAPE, NULL);
|
||||
|
||||
if (!ottie_parser_parse_object (reader, "path shape", options, G_N_ELEMENTS (options), self))
|
||||
{
|
||||
g_object_unref (self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return OTTIE_SHAPE (self);
|
||||
}
|
||||
|
||||
45
ottie/ottiepathshapeprivate.h
Normal file
45
ottie/ottiepathshapeprivate.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_PATH_SHAPE_PRIVATE_H__
|
||||
#define __OTTIE_PATH_SHAPE_PRIVATE_H__
|
||||
|
||||
#include "ottieshapeprivate.h"
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OTTIE_TYPE_PATH_SHAPE (ottie_path_shape_get_type ())
|
||||
#define OTTIE_PATH_SHAPE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OTTIE_TYPE_PATH_SHAPE, OttiePathShape))
|
||||
#define OTTIE_PATH_SHAPE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), OTTIE_TYPE_PATH_SHAPE, OttiePathShapeClass))
|
||||
#define OTTIE_IS_PATH_SHAPE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OTTIE_TYPE_PATH_SHAPE))
|
||||
#define OTTIE_IS_PATH_SHAPE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OTTIE_TYPE_PATH_SHAPE))
|
||||
#define OTTIE_PATH_SHAPE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OTTIE_TYPE_PATH_SHAPE, OttiePathShapeClass))
|
||||
|
||||
typedef struct _OttiePathShape OttiePathShape;
|
||||
typedef struct _OttiePathShapeClass OttiePathShapeClass;
|
||||
|
||||
GType ottie_path_shape_get_type (void) G_GNUC_CONST;
|
||||
|
||||
OttieShape * ottie_path_shape_parse (JsonReader *reader);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_PATH_SHAPE_PRIVATE_H__ */
|
||||
402
ottie/ottiepathvalue.c
Normal file
402
ottie/ottiepathvalue.c
Normal file
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottiepathvalueprivate.h"
|
||||
|
||||
#include "ottieparserprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
typedef struct _OttieContour OttieContour;
|
||||
typedef struct _OttieCurve OttieCurve;
|
||||
typedef struct _OttiePath OttiePath;
|
||||
|
||||
struct _OttieCurve {
|
||||
double point[2];
|
||||
double in[2];
|
||||
double out[2];
|
||||
};
|
||||
|
||||
struct _OttieContour {
|
||||
gboolean closed;
|
||||
guint n_curves;
|
||||
OttieCurve curves[0];
|
||||
};
|
||||
|
||||
struct _OttiePath {
|
||||
guint ref_count;
|
||||
guint n_contours;
|
||||
OttieContour *contours[];
|
||||
};
|
||||
|
||||
static OttieContour *
|
||||
ottie_contour_renew (OttieContour *path,
|
||||
guint n_curves)
|
||||
{
|
||||
OttieContour *self;
|
||||
|
||||
self = g_realloc (path, sizeof (OttieContour) + n_curves * sizeof (OttieCurve));
|
||||
self->n_curves = n_curves;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static OttieContour *
|
||||
ottie_contour_new (gboolean closed,
|
||||
guint n_curves)
|
||||
{
|
||||
OttieContour *self;
|
||||
|
||||
self = g_malloc0 (sizeof (OttieContour) + n_curves * sizeof (OttieCurve));
|
||||
self->closed = closed;
|
||||
self->n_curves = n_curves;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_contour_free (OttieContour *path)
|
||||
{
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_parse_value_parse_numbers (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
return ottie_parser_parse_array (reader, "number",
|
||||
2, 2, NULL,
|
||||
offset, sizeof (double),
|
||||
ottie_parser_option_double, data);
|
||||
}
|
||||
|
||||
#define MAKE_OPEN_CONTOUR (NULL)
|
||||
#define MAKE_CLOSED_CONTOUR GSIZE_TO_POINTER(1)
|
||||
static gboolean
|
||||
ottie_parse_value_parse_curve_array (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
/* Attention: The offset value here is to the point in the curve, not
|
||||
* to the target */
|
||||
OttieContour **target = (OttieContour **) data;
|
||||
OttieContour *path = *target;
|
||||
guint n_curves;
|
||||
|
||||
n_curves = json_reader_count_elements (reader);
|
||||
if (path == MAKE_OPEN_CONTOUR)
|
||||
path = ottie_contour_new (FALSE, n_curves);
|
||||
else if (path == MAKE_CLOSED_CONTOUR)
|
||||
path = ottie_contour_new (TRUE, n_curves);
|
||||
else if (n_curves < path->n_curves)
|
||||
path = ottie_contour_renew (path, n_curves);
|
||||
else if (n_curves > path->n_curves)
|
||||
n_curves = path->n_curves;
|
||||
|
||||
*target = path;
|
||||
|
||||
return ottie_parser_parse_array (reader, "path array",
|
||||
0, path->n_curves, NULL,
|
||||
offset, sizeof (OttieCurve),
|
||||
ottie_parse_value_parse_numbers, &path->curves[0]);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_parser_value_parse_closed (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttieContour **target = (OttieContour **) data;
|
||||
gboolean b;
|
||||
|
||||
b = json_reader_get_boolean_value (reader);
|
||||
if (json_reader_get_error (reader))
|
||||
{
|
||||
ottie_parser_emit_error (reader, json_reader_get_error (reader));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (*target == MAKE_OPEN_CONTOUR || *target == MAKE_CLOSED_CONTOUR)
|
||||
{
|
||||
if (b)
|
||||
*target = MAKE_CLOSED_CONTOUR;
|
||||
else
|
||||
*target = MAKE_OPEN_CONTOUR;
|
||||
}
|
||||
else
|
||||
(*target)->closed = b;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_path_value_parse_contour (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttieContour **target = (OttieContour **) ((guint8 *) data + offset);
|
||||
OttieParserOption options[] = {
|
||||
{ "c", ottie_parser_value_parse_closed, 0 },
|
||||
{ "i", ottie_parse_value_parse_curve_array, G_STRUCT_OFFSET (OttieCurve, in) },
|
||||
{ "o", ottie_parse_value_parse_curve_array, G_STRUCT_OFFSET (OttieCurve, out) },
|
||||
{ "v", ottie_parse_value_parse_curve_array, G_STRUCT_OFFSET (OttieCurve, point) },
|
||||
};
|
||||
|
||||
g_assert (*target == NULL);
|
||||
*target = MAKE_CLOSED_CONTOUR;
|
||||
|
||||
if (!ottie_parser_parse_object (reader, "contour", options, G_N_ELEMENTS (options), target))
|
||||
{
|
||||
if (*target != MAKE_OPEN_CONTOUR && *target != MAKE_CLOSED_CONTOUR)
|
||||
g_clear_pointer (target, ottie_contour_free);
|
||||
*target = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (*target == MAKE_OPEN_CONTOUR)
|
||||
*target = ottie_contour_new (FALSE, 0);
|
||||
else if (*target == MAKE_CLOSED_CONTOUR)
|
||||
*target = ottie_contour_new (TRUE, 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static OttiePath *
|
||||
ottie_path_new (gsize n_contours)
|
||||
{
|
||||
OttiePath *self;
|
||||
|
||||
self = g_malloc0 (sizeof (OttiePath) + sizeof (OttieContour *) * n_contours);
|
||||
self->ref_count = 1;
|
||||
self->n_contours = n_contours;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static OttiePath *
|
||||
ottie_path_ref (OttiePath *self)
|
||||
{
|
||||
self->ref_count++;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_path_unref (OttiePath *self)
|
||||
{
|
||||
self->ref_count--;
|
||||
if (self->ref_count > 0)
|
||||
return;
|
||||
|
||||
for (guint i = 0; i < self->n_contours; i++)
|
||||
{
|
||||
g_clear_pointer (&self->contours[i], ottie_contour_free);
|
||||
}
|
||||
|
||||
g_free (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_path_value_parse_one (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttiePath **target = (OttiePath **) ((guint8 *) data + offset);
|
||||
OttiePath *path;
|
||||
|
||||
if (json_reader_is_array (reader))
|
||||
path = ottie_path_new (json_reader_count_elements (reader));
|
||||
else
|
||||
path = ottie_path_new (1);
|
||||
|
||||
if (!ottie_parser_parse_array (reader, "path",
|
||||
path->n_contours, path->n_contours, NULL,
|
||||
G_STRUCT_OFFSET (OttiePath, contours),
|
||||
sizeof (OttieContour *),
|
||||
ottie_path_value_parse_contour, path))
|
||||
{
|
||||
ottie_path_unref (path);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_clear_pointer (target, ottie_path_unref);
|
||||
*target = path;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static OttieContour *
|
||||
ottie_contour_interpolate (const OttieContour *start,
|
||||
const OttieContour *end,
|
||||
double progress)
|
||||
{
|
||||
OttieContour *self = ottie_contour_new (start->closed || end->closed,
|
||||
MIN (start->n_curves, end->n_curves));
|
||||
|
||||
for (gsize i = 0; i < self->n_curves; i++)
|
||||
{
|
||||
self->curves[i].point[0] = start->curves[i].point[0] + progress * (end->curves[i].point[0] - start->curves[i].point[0]);
|
||||
self->curves[i].point[1] = start->curves[i].point[1] + progress * (end->curves[i].point[1] - start->curves[i].point[1]);
|
||||
self->curves[i].in[0] = start->curves[i].in[0] + progress * (end->curves[i].in[0] - start->curves[i].in[0]);
|
||||
self->curves[i].in[1] = start->curves[i].in[1] + progress * (end->curves[i].in[1] - start->curves[i].in[1]);
|
||||
self->curves[i].out[0] = start->curves[i].out[0] + progress * (end->curves[i].out[0] - start->curves[i].out[0]);
|
||||
self->curves[i].out[1] = start->curves[i].out[1] + progress * (end->curves[i].out[1] - start->curves[i].out[1]);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static OttiePath *
|
||||
ottie_path_interpolate (const OttiePath *start,
|
||||
const OttiePath *end,
|
||||
double progress)
|
||||
{
|
||||
OttiePath *self = ottie_path_new (MIN (start->n_contours, end->n_contours));
|
||||
|
||||
for (gsize i = 0; i < self->n_contours; i++)
|
||||
{
|
||||
self->contours[i] = ottie_contour_interpolate (start->contours[i],
|
||||
end->contours[i],
|
||||
progress);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#define OTTIE_KEYFRAMES_NAME ottie_path_keyframes
|
||||
#define OTTIE_KEYFRAMES_TYPE_NAME OttieContourKeyframes
|
||||
#define OTTIE_KEYFRAMES_ELEMENT_TYPE OttiePath *
|
||||
#define OTTIE_KEYFRAMES_COPY_FUNC ottie_path_ref
|
||||
#define OTTIE_KEYFRAMES_FREE_FUNC ottie_path_unref
|
||||
#define OTTIE_KEYFRAMES_PARSE_FUNC ottie_path_value_parse_one
|
||||
#define OTTIE_KEYFRAMES_INTERPOLATE_FUNC ottie_path_interpolate
|
||||
#include "ottiekeyframesimpl.c"
|
||||
|
||||
void
|
||||
ottie_path_value_init (OttiePathValue *self)
|
||||
{
|
||||
self->is_static = TRUE;
|
||||
self->static_value = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ottie_path_value_clear (OttiePathValue *self)
|
||||
{
|
||||
if (self->is_static)
|
||||
g_clear_pointer (&self->static_value, ottie_path_unref);
|
||||
else
|
||||
g_clear_pointer (&self->keyframes, ottie_path_keyframes_free);
|
||||
}
|
||||
|
||||
static GskPath *
|
||||
ottie_path_build (OttiePath *self,
|
||||
gboolean reverse)
|
||||
{
|
||||
GskPathBuilder *builder;
|
||||
|
||||
if (reverse)
|
||||
g_warning ("FIXME: Make paths reversible");
|
||||
|
||||
builder = gsk_path_builder_new ();
|
||||
for (gsize i = 0; i < self->n_contours; i++)
|
||||
{
|
||||
OttieContour *contour = self->contours[i];
|
||||
if (contour->n_curves == 0)
|
||||
continue;
|
||||
|
||||
gsk_path_builder_move_to (builder,
|
||||
contour->curves[0].point[0], contour->curves[0].point[1]);
|
||||
for (guint j = 1; j < contour->n_curves; j++)
|
||||
{
|
||||
gsk_path_builder_curve_to (builder,
|
||||
contour->curves[j-1].point[0] + contour->curves[j-1].out[0],
|
||||
contour->curves[j-1].point[1] + contour->curves[j-1].out[1],
|
||||
contour->curves[j].point[0] + contour->curves[j].in[0],
|
||||
contour->curves[j].point[1] + contour->curves[j].in[1],
|
||||
contour->curves[j].point[0],
|
||||
contour->curves[j].point[1]);
|
||||
}
|
||||
if (contour->closed)
|
||||
{
|
||||
gsk_path_builder_curve_to (builder,
|
||||
contour->curves[contour->n_curves-1].point[0] + contour->curves[contour->n_curves-1].out[0],
|
||||
contour->curves[contour->n_curves-1].point[1] + contour->curves[contour->n_curves-1].out[1],
|
||||
contour->curves[0].point[0] + contour->curves[0].in[0],
|
||||
contour->curves[0].point[1] + contour->curves[0].in[1],
|
||||
contour->curves[0].point[0],
|
||||
contour->curves[0].point[1]);
|
||||
gsk_path_builder_close (builder);
|
||||
}
|
||||
}
|
||||
|
||||
return gsk_path_builder_free_to_path (builder);
|
||||
}
|
||||
|
||||
GskPath *
|
||||
ottie_path_value_get (OttiePathValue *self,
|
||||
double timestamp,
|
||||
gboolean reverse)
|
||||
{
|
||||
if (self->is_static)
|
||||
return ottie_path_build (self->static_value, reverse);
|
||||
|
||||
return ottie_path_build (ottie_path_keyframes_get (self->keyframes, timestamp), reverse);
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_path_value_parse (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttiePathValue *self = (OttiePathValue *) ((guint8 *) data + GPOINTER_TO_SIZE (offset));
|
||||
|
||||
if (json_reader_read_member (reader, "k"))
|
||||
{
|
||||
if (!json_reader_is_array (reader))
|
||||
{
|
||||
if (!ottie_path_value_parse_one (reader, 0, &self->static_value))
|
||||
{
|
||||
json_reader_end_member (reader);
|
||||
return FALSE;
|
||||
}
|
||||
self->is_static = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->keyframes = ottie_path_keyframes_parse (reader);
|
||||
if (self->keyframes == NULL)
|
||||
{
|
||||
json_reader_end_member (reader);
|
||||
return FALSE;
|
||||
}
|
||||
self->is_static = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "Property is not a path value");
|
||||
}
|
||||
json_reader_end_member (reader);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
53
ottie/ottiepathvalueprivate.h
Normal file
53
ottie/ottiepathvalueprivate.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_PATH_VALUE_PRIVATE_H__
|
||||
#define __OTTIE_PATH_VALUE_PRIVATE_H__
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
#include <gsk/gsk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _OttiePathValue OttiePathValue;
|
||||
|
||||
struct _OttiePathValue
|
||||
{
|
||||
gboolean is_static;
|
||||
union {
|
||||
gpointer static_value;
|
||||
gpointer keyframes;
|
||||
};
|
||||
};
|
||||
|
||||
void ottie_path_value_init (OttiePathValue *self);
|
||||
void ottie_path_value_clear (OttiePathValue *self);
|
||||
|
||||
GskPath * ottie_path_value_get (OttiePathValue *self,
|
||||
double timestamp,
|
||||
gboolean reverse);
|
||||
|
||||
gboolean ottie_path_value_parse (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_PATH_VALUE_PRIVATE_H__ */
|
||||
490
ottie/ottieplayer.c
Normal file
490
ottie/ottieplayer.c
Normal file
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottieplayer.h"
|
||||
|
||||
#include "ottiecreation.h"
|
||||
#include "ottiepaintable.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
struct _OttiePlayer
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GFile *file;
|
||||
|
||||
OttieCreation *creation;
|
||||
OttiePaintable *paintable;
|
||||
gint64 time_offset;
|
||||
guint timer_cb;
|
||||
};
|
||||
|
||||
struct _OttiePlayerClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_FILE,
|
||||
|
||||
N_PROPS,
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
ottie_player_paintable_snapshot (GdkPaintable *paintable,
|
||||
GdkSnapshot *snapshot,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
OttiePlayer *self = OTTIE_PLAYER (paintable);
|
||||
|
||||
gdk_paintable_snapshot (GDK_PAINTABLE (self->paintable), snapshot, width, height);
|
||||
}
|
||||
|
||||
static int
|
||||
ottie_player_paintable_get_intrinsic_width (GdkPaintable *paintable)
|
||||
{
|
||||
OttiePlayer *self = OTTIE_PLAYER (paintable);
|
||||
|
||||
return gdk_paintable_get_intrinsic_width (GDK_PAINTABLE (self->paintable));
|
||||
}
|
||||
|
||||
static int
|
||||
ottie_player_paintable_get_intrinsic_height (GdkPaintable *paintable)
|
||||
{
|
||||
OttiePlayer *self = OTTIE_PLAYER (paintable);
|
||||
|
||||
return gdk_paintable_get_intrinsic_height (GDK_PAINTABLE (self->paintable));
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_player_paintable_init (GdkPaintableInterface *iface)
|
||||
{
|
||||
iface->snapshot = ottie_player_paintable_snapshot;
|
||||
iface->get_intrinsic_width = ottie_player_paintable_get_intrinsic_width;
|
||||
iface->get_intrinsic_height = ottie_player_paintable_get_intrinsic_height;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (OttiePlayer, ottie_player, GTK_TYPE_MEDIA_STREAM, 0,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||
ottie_player_paintable_init))
|
||||
|
||||
static gboolean
|
||||
ottie_player_timer_cb (gpointer data)
|
||||
{
|
||||
OttiePlayer *self = OTTIE_PLAYER (data);
|
||||
gint64 timestamp;
|
||||
|
||||
timestamp = g_get_monotonic_time () - self->time_offset;
|
||||
if (timestamp > ottie_paintable_get_duration (self->paintable))
|
||||
{
|
||||
if (gtk_media_stream_get_loop (GTK_MEDIA_STREAM (self)))
|
||||
{
|
||||
timestamp %= ottie_paintable_get_duration (self->paintable);
|
||||
}
|
||||
else
|
||||
{
|
||||
timestamp = ottie_paintable_get_duration (self->paintable);
|
||||
gtk_media_stream_ended (GTK_MEDIA_STREAM (self));
|
||||
}
|
||||
}
|
||||
ottie_paintable_set_timestamp (self->paintable, timestamp);
|
||||
gtk_media_stream_update (GTK_MEDIA_STREAM (self), timestamp);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_player_play (GtkMediaStream *stream)
|
||||
{
|
||||
OttiePlayer *self = OTTIE_PLAYER (stream);
|
||||
double frame_rate;
|
||||
|
||||
frame_rate = ottie_creation_get_frame_rate (self->creation);
|
||||
if (frame_rate <= 0)
|
||||
return FALSE;
|
||||
|
||||
self->time_offset = g_get_monotonic_time () - ottie_paintable_get_timestamp (self->paintable);
|
||||
self->timer_cb = g_timeout_add (1000 / frame_rate, ottie_player_timer_cb, self);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_player_pause (GtkMediaStream *stream)
|
||||
{
|
||||
OttiePlayer *self = OTTIE_PLAYER (stream);
|
||||
|
||||
g_clear_handle_id (&self->timer_cb, g_source_remove);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_player_seek (GtkMediaStream *stream,
|
||||
gint64 timestamp)
|
||||
{
|
||||
OttiePlayer *self = OTTIE_PLAYER (stream);
|
||||
|
||||
if (!ottie_creation_is_prepared (self->creation))
|
||||
gtk_media_stream_seek_failed (stream);
|
||||
|
||||
ottie_paintable_set_timestamp (self->paintable, timestamp);
|
||||
self->time_offset = g_get_monotonic_time () - timestamp;
|
||||
|
||||
gtk_media_stream_seek_success (stream);
|
||||
gtk_media_stream_update (stream, timestamp);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_player_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
|
||||
{
|
||||
OttiePlayer *self = OTTIE_PLAYER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_FILE:
|
||||
ottie_player_set_file (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_player_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
OttiePlayer *self = OTTIE_PLAYER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_FILE:
|
||||
g_value_set_object (value, self->file);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_player_dispose (GObject *object)
|
||||
{
|
||||
OttiePlayer *self = OTTIE_PLAYER (object);
|
||||
|
||||
if (self->paintable)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (self->paintable, gdk_paintable_invalidate_contents, self);
|
||||
g_signal_handlers_disconnect_by_func (self->paintable, gdk_paintable_invalidate_size, self);
|
||||
g_clear_object (&self->paintable);
|
||||
}
|
||||
g_clear_object (&self->creation);
|
||||
|
||||
G_OBJECT_CLASS (ottie_player_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_player_class_init (OttiePlayerClass *klass)
|
||||
{
|
||||
GtkMediaStreamClass *stream_class = GTK_MEDIA_STREAM_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
stream_class->play = ottie_player_play;
|
||||
stream_class->pause = ottie_player_pause;
|
||||
stream_class->seek = ottie_player_seek;
|
||||
|
||||
gobject_class->get_property = ottie_player_get_property;
|
||||
gobject_class->set_property = ottie_player_set_property;
|
||||
gobject_class->dispose = ottie_player_dispose;
|
||||
|
||||
/**
|
||||
* OttiePlayer:file
|
||||
*
|
||||
* The played file or %NULL.
|
||||
*/
|
||||
properties[PROP_FILE] =
|
||||
g_param_spec_object ("file",
|
||||
_("File"),
|
||||
_("The played file"),
|
||||
G_TYPE_FILE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_player_prepared_cb (OttieCreation *creation,
|
||||
GParamSpec *pspec,
|
||||
OttiePlayer *self)
|
||||
{
|
||||
if (ottie_creation_is_prepared (creation))
|
||||
gtk_media_stream_prepared (GTK_MEDIA_STREAM (self),
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
ottie_paintable_get_duration (self->paintable));
|
||||
else
|
||||
gtk_media_stream_unprepared (GTK_MEDIA_STREAM (self));
|
||||
|
||||
ottie_paintable_set_timestamp (self->paintable, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_player_init (OttiePlayer *self)
|
||||
{
|
||||
self->creation = ottie_creation_new ();
|
||||
g_signal_connect (self->creation, "notify::prepared", G_CALLBACK (ottie_player_prepared_cb), self);
|
||||
self->paintable = ottie_paintable_new (self->creation);
|
||||
g_signal_connect_swapped (self->paintable, "invalidate-contents", G_CALLBACK (gdk_paintable_invalidate_contents), self);
|
||||
g_signal_connect_swapped (self->paintable, "invalidate-size", G_CALLBACK (gdk_paintable_invalidate_size), self);
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_player_new:
|
||||
*
|
||||
* Creates a new Ottie player.
|
||||
*
|
||||
* Returns: (transfer full): a new #OttiePlayer
|
||||
**/
|
||||
OttiePlayer *
|
||||
ottie_player_new (void)
|
||||
{
|
||||
return g_object_new (OTTIE_TYPE_PLAYER, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_player_new_for_file:
|
||||
* @file: (nullable): a #GFile
|
||||
*
|
||||
* Creates a new #OttiePlayer playing the given @file. If the file
|
||||
* isn’t found or can’t be loaded, the resulting #OttiePlayer be empty.
|
||||
*
|
||||
* Returns: a new #OttiePlayer
|
||||
**/
|
||||
OttiePlayer*
|
||||
ottie_player_new_for_file (GFile *file)
|
||||
{
|
||||
g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
|
||||
|
||||
return g_object_new (OTTIE_TYPE_PLAYER,
|
||||
"file", file,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_player_new_for_filename:
|
||||
* @filename: (type filename) (nullable): a filename
|
||||
*
|
||||
* Creates a new #OttiePlayer displaying the file @filename.
|
||||
*
|
||||
* This is a utility function that calls ottie_player_new_for_file().
|
||||
* See that function for details.
|
||||
*
|
||||
* Returns: a new #OttiePlayer
|
||||
**/
|
||||
OttiePlayer*
|
||||
ottie_player_new_for_filename (const char *filename)
|
||||
{
|
||||
OttiePlayer *result;
|
||||
GFile *file;
|
||||
|
||||
if (filename)
|
||||
file = g_file_new_for_path (filename);
|
||||
else
|
||||
file = NULL;
|
||||
|
||||
result = ottie_player_new_for_file (file);
|
||||
|
||||
if (file)
|
||||
g_object_unref (file);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_player_new_for_resource:
|
||||
* @resource_path: (nullable): resource path to play back
|
||||
*
|
||||
* Creates a new #OttiePlayer displaying the file @resource_path.
|
||||
*
|
||||
* This is a utility function that calls ottie_player_new_for_file().
|
||||
* See that function for details.
|
||||
*
|
||||
* Returns: a new #OttiePlayer
|
||||
**/
|
||||
OttiePlayer *
|
||||
ottie_player_new_for_resource (const char *resource_path)
|
||||
{
|
||||
OttiePlayer *result;
|
||||
GFile *file;
|
||||
|
||||
if (resource_path)
|
||||
{
|
||||
char *uri, *escaped;
|
||||
|
||||
escaped = g_uri_escape_string (resource_path,
|
||||
G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
|
||||
uri = g_strconcat ("resource://", escaped, NULL);
|
||||
g_free (escaped);
|
||||
|
||||
file = g_file_new_for_uri (uri);
|
||||
g_free (uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
result = ottie_player_new_for_file (file);
|
||||
|
||||
if (file)
|
||||
g_object_unref (file);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_player_set_file:
|
||||
* @self: a #OttiePlayer
|
||||
* @file: (nullable): a %GFile or %NULL
|
||||
*
|
||||
* Makes @self load and display @file.
|
||||
*
|
||||
* See ottie_player_new_for_file() for details.
|
||||
**/
|
||||
void
|
||||
ottie_player_set_file (OttiePlayer *self,
|
||||
GFile *file)
|
||||
{
|
||||
g_return_if_fail (OTTIE_IS_PLAYER (self));
|
||||
g_return_if_fail (file == NULL || G_IS_FILE (file));
|
||||
|
||||
if (self->file == file)
|
||||
return;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
g_set_object (&self->file, file);
|
||||
ottie_creation_load_file (self->creation, file);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FILE]);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_player_get_file:
|
||||
* @self: a #OttiePlayer
|
||||
*
|
||||
* Gets the #GFile currently displayed if @self is displaying a file.
|
||||
* If @self is not displaying a file, then %NULL is returned.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): The #GFile displayed by @self.
|
||||
**/
|
||||
GFile *
|
||||
ottie_player_get_file (OttiePlayer *self)
|
||||
{
|
||||
g_return_val_if_fail (OTTIE_IS_PLAYER (self), FALSE);
|
||||
|
||||
return self->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_player_set_filename:
|
||||
* @self: a #OttiePlayer
|
||||
* @filename: (nullable): the filename to play
|
||||
*
|
||||
* Makes @self load and display the given @filename.
|
||||
*
|
||||
* This is a utility function that calls ottie_player_set_file().
|
||||
**/
|
||||
void
|
||||
ottie_player_set_filename (OttiePlayer *self,
|
||||
const char *filename)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
g_return_if_fail (OTTIE_IS_PLAYER (self));
|
||||
|
||||
if (filename)
|
||||
file = g_file_new_for_path (filename);
|
||||
else
|
||||
file = NULL;
|
||||
|
||||
ottie_player_set_file (self, file);
|
||||
|
||||
if (file)
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
/**
|
||||
* ottie_player_set_resource:
|
||||
* @self: a #OttiePlayer
|
||||
* @resource_path: (nullable): the resource to set
|
||||
*
|
||||
* Makes @self load and display the resource at the given
|
||||
* @resource_path.
|
||||
*
|
||||
* This is a utility function that calls ottie_player_set_file(),
|
||||
**/
|
||||
void
|
||||
ottie_player_set_resource (OttiePlayer *self,
|
||||
const char *resource_path)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
g_return_if_fail (OTTIE_IS_PLAYER (self));
|
||||
|
||||
if (resource_path)
|
||||
{
|
||||
char *uri, *escaped;
|
||||
|
||||
escaped = g_uri_escape_string (resource_path,
|
||||
G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
|
||||
uri = g_strconcat ("resource://", escaped, NULL);
|
||||
g_free (escaped);
|
||||
|
||||
file = g_file_new_for_uri (uri);
|
||||
g_free (uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
ottie_player_set_file (self, file);
|
||||
|
||||
if (file)
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
59
ottie/ottieplayer.h
Normal file
59
ottie/ottieplayer.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_PLAYER_H__
|
||||
#define __OTTIE_PLAYER_H__
|
||||
|
||||
#if !defined (__OTTIE_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <ottie/ottie.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OTTIE_TYPE_PLAYER (ottie_player_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (OttiePlayer, ottie_player, OTTIE, PLAYER, GtkMediaStream)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
OttiePlayer * ottie_player_new (void);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
OttiePlayer * ottie_player_new_for_file (GFile *file);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
OttiePlayer * ottie_player_new_for_filename (const char *filename);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
OttiePlayer * ottie_player_new_for_resource (const char *resource_path);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void ottie_player_set_file (OttiePlayer *self,
|
||||
GFile *file);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GFile * ottie_player_get_file (OttiePlayer *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void ottie_player_set_filename (OttiePlayer *self,
|
||||
const char *filename);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void ottie_player_set_resource (OttiePlayer *self,
|
||||
const char *resource_path);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_PLAYER_H__ */
|
||||
154
ottie/ottiepoint3dvalue.c
Normal file
154
ottie/ottiepoint3dvalue.c
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottiepoint3dvalueprivate.h"
|
||||
|
||||
#include "ottieparserprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
static gboolean
|
||||
ottie_point3d_value_parse_value (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
double d[3];
|
||||
guint n_items;
|
||||
|
||||
if (!ottie_parser_parse_array (reader, "point",
|
||||
2, 3, &n_items,
|
||||
0, sizeof (double),
|
||||
ottie_parser_option_double,
|
||||
&d))
|
||||
return FALSE;
|
||||
|
||||
if (n_items == 2)
|
||||
d[2] = NAN; /* We do fixup below */
|
||||
|
||||
*(graphene_point3d_t *) ((guint8 *) data + offset) = GRAPHENE_POINT3D_INIT (d[0], d[1], d[2]);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define OTTIE_KEYFRAMES_NAME ottie_point_keyframes
|
||||
#define OTTIE_KEYFRAMES_TYPE_NAME OttiePointKeyframes
|
||||
#define OTTIE_KEYFRAMES_ELEMENT_TYPE graphene_point3d_t
|
||||
#define OTTIE_KEYFRAMES_BY_VALUE 1
|
||||
#define OTTIE_KEYFRAMES_DIMENSIONS 3
|
||||
#define OTTIE_KEYFRAMES_PARSE_FUNC ottie_point3d_value_parse_value
|
||||
#define OTTIE_KEYFRAMES_INTERPOLATE_FUNC graphene_point3d_interpolate
|
||||
#include "ottiekeyframesimpl.c"
|
||||
|
||||
void
|
||||
ottie_point3d_value_init (OttiePoint3DValue *self,
|
||||
const graphene_point3d_t *value)
|
||||
{
|
||||
self->is_static = TRUE;
|
||||
self->static_value = *value;
|
||||
}
|
||||
|
||||
void
|
||||
ottie_point3d_value_clear (OttiePoint3DValue *self)
|
||||
{
|
||||
if (!self->is_static)
|
||||
g_clear_pointer (&self->keyframes, ottie_point_keyframes_free);
|
||||
}
|
||||
|
||||
void
|
||||
ottie_point3d_value_get (OttiePoint3DValue *self,
|
||||
double timestamp,
|
||||
graphene_point3d_t *value)
|
||||
{
|
||||
if (self->is_static)
|
||||
{
|
||||
*value = self->static_value;
|
||||
return;
|
||||
}
|
||||
|
||||
ottie_point_keyframes_get (self->keyframes, timestamp, value);
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_point3d_value_parse (JsonReader *reader,
|
||||
float default_value,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttiePoint3DValue *self = (OttiePoint3DValue *) ((guint8 *) data + offset);
|
||||
|
||||
if (json_reader_read_member (reader, "k"))
|
||||
{
|
||||
gboolean is_static;
|
||||
|
||||
if (!json_reader_is_array (reader))
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "Point value needs an array for its value");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!json_reader_read_element (reader, 0))
|
||||
{
|
||||
ottie_parser_emit_error (reader, json_reader_get_error (reader));
|
||||
json_reader_end_element (reader);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
is_static = !json_reader_is_object (reader);
|
||||
json_reader_end_element (reader);
|
||||
|
||||
if (is_static)
|
||||
{
|
||||
if (!ottie_point3d_value_parse_value (reader, 0, &self->static_value))
|
||||
{
|
||||
json_reader_end_member (reader);
|
||||
return FALSE;
|
||||
}
|
||||
if (isnan (self->static_value.z))
|
||||
self->static_value.z = default_value;
|
||||
self->is_static = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
OttiePointKeyframes *keyframes = ottie_point_keyframes_parse (reader);
|
||||
if (keyframes == NULL)
|
||||
{
|
||||
json_reader_end_member (reader);
|
||||
return FALSE;
|
||||
}
|
||||
for (int i = 0; i < keyframes->n_items; i++)
|
||||
{
|
||||
if (isnan (keyframes->items[i].start_value.z))
|
||||
keyframes->items[i].start_value.z = default_value;
|
||||
if (isnan (keyframes->items[i].end_value.z))
|
||||
keyframes->items[i].end_value.z = default_value;
|
||||
}
|
||||
self->is_static = FALSE;
|
||||
self->keyframes = keyframes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "Point value has no value");
|
||||
}
|
||||
json_reader_end_member (reader);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
54
ottie/ottiepoint3dvalueprivate.h
Normal file
54
ottie/ottiepoint3dvalueprivate.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_POINT3D_VALUE_PRIVATE_H__
|
||||
#define __OTTIE_POINT3D_VALUE_PRIVATE_H__
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
#include <graphene.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _OttiePoint3DValue OttiePoint3DValue;
|
||||
|
||||
struct _OttiePoint3DValue
|
||||
{
|
||||
gboolean is_static;
|
||||
union {
|
||||
graphene_point3d_t static_value;
|
||||
gpointer keyframes;
|
||||
};
|
||||
};
|
||||
|
||||
void ottie_point3d_value_init (OttiePoint3DValue *self,
|
||||
const graphene_point3d_t *value);
|
||||
void ottie_point3d_value_clear (OttiePoint3DValue *self);
|
||||
|
||||
void ottie_point3d_value_get (OttiePoint3DValue *self,
|
||||
double timestamp,
|
||||
graphene_point3d_t *value);
|
||||
|
||||
gboolean ottie_point3d_value_parse (JsonReader *reader,
|
||||
float default_value,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_POINT3D_VALUE_PRIVATE_H__ */
|
||||
140
ottie/ottiepointvalue.c
Normal file
140
ottie/ottiepointvalue.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottiepointvalueprivate.h"
|
||||
|
||||
#include "ottieparserprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
static gboolean
|
||||
ottie_point_value_parse_value (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
double d[2];
|
||||
|
||||
if (!ottie_parser_parse_array (reader, "point",
|
||||
2, 2, NULL,
|
||||
0, sizeof (double),
|
||||
ottie_parser_option_double,
|
||||
&d))
|
||||
return FALSE;
|
||||
|
||||
*(graphene_point_t *) ((guint8 *) data + offset) = GRAPHENE_POINT_INIT (d[0], d[1]);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define OTTIE_KEYFRAMES_NAME ottie_point_keyframes
|
||||
#define OTTIE_KEYFRAMES_TYPE_NAME OttiePointKeyframes
|
||||
#define OTTIE_KEYFRAMES_ELEMENT_TYPE graphene_point_t
|
||||
#define OTTIE_KEYFRAMES_BY_VALUE 1
|
||||
#define OTTIE_KEYFRAMES_DIMENSIONS 2
|
||||
#define OTTIE_KEYFRAMES_PARSE_FUNC ottie_point_value_parse_value
|
||||
#define OTTIE_KEYFRAMES_INTERPOLATE_FUNC graphene_point_interpolate
|
||||
#include "ottiekeyframesimpl.c"
|
||||
|
||||
void
|
||||
ottie_point_value_init (OttiePointValue *self,
|
||||
const graphene_point_t *value)
|
||||
{
|
||||
self->is_static = TRUE;
|
||||
self->static_value = *value;
|
||||
}
|
||||
|
||||
void
|
||||
ottie_point_value_clear (OttiePointValue *self)
|
||||
{
|
||||
if (!self->is_static)
|
||||
g_clear_pointer (&self->keyframes, ottie_point_keyframes_free);
|
||||
}
|
||||
|
||||
void
|
||||
ottie_point_value_get (OttiePointValue *self,
|
||||
double timestamp,
|
||||
graphene_point_t *value)
|
||||
{
|
||||
if (self->is_static)
|
||||
{
|
||||
*value = self->static_value;
|
||||
return;
|
||||
}
|
||||
|
||||
ottie_point_keyframes_get (self->keyframes, timestamp, value);
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_point_value_parse (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttiePointValue *self = (OttiePointValue *) ((guint8 *) data + offset);
|
||||
|
||||
if (json_reader_read_member (reader, "k"))
|
||||
{
|
||||
gboolean is_static;
|
||||
|
||||
if (!json_reader_is_array (reader))
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "Point value needs an array for its value");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!json_reader_read_element (reader, 0))
|
||||
{
|
||||
ottie_parser_emit_error (reader, json_reader_get_error (reader));
|
||||
json_reader_end_element (reader);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
is_static = !json_reader_is_object (reader);
|
||||
json_reader_end_element (reader);
|
||||
|
||||
if (is_static)
|
||||
{
|
||||
if (!ottie_point_value_parse_value (reader, 0, &self->static_value))
|
||||
{
|
||||
json_reader_end_member (reader);
|
||||
return FALSE;
|
||||
}
|
||||
self->is_static = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
OttiePointKeyframes *keyframes = ottie_point_keyframes_parse (reader);
|
||||
if (keyframes == NULL)
|
||||
{
|
||||
json_reader_end_member (reader);
|
||||
return FALSE;
|
||||
}
|
||||
self->is_static = FALSE;
|
||||
self->keyframes = keyframes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "Point value has no value");
|
||||
}
|
||||
json_reader_end_member (reader);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
53
ottie/ottiepointvalueprivate.h
Normal file
53
ottie/ottiepointvalueprivate.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_POINT_VALUE_PRIVATE_H__
|
||||
#define __OTTIE_POINT_VALUE_PRIVATE_H__
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
#include <graphene.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _OttiePointValue OttiePointValue;
|
||||
|
||||
struct _OttiePointValue
|
||||
{
|
||||
gboolean is_static;
|
||||
union {
|
||||
graphene_point_t static_value;
|
||||
gpointer keyframes;
|
||||
};
|
||||
};
|
||||
|
||||
void ottie_point_value_init (OttiePointValue *self,
|
||||
const graphene_point_t *value);
|
||||
void ottie_point_value_clear (OttiePointValue *self);
|
||||
|
||||
void ottie_point_value_get (OttiePointValue *self,
|
||||
double timestamp,
|
||||
graphene_point_t *value);
|
||||
|
||||
gboolean ottie_point_value_parse (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_POINT_VALUE_PRIVATE_H__ */
|
||||
177
ottie/ottieprecomp.c
Normal file
177
ottie/ottieprecomp.c
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottieprecompprivate.h"
|
||||
|
||||
#include "ottieparserprivate.h"
|
||||
#include "ottieprecomplayerprivate.h"
|
||||
#include "ottieshapelayerprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gsk/gsk.h>
|
||||
|
||||
#define GDK_ARRAY_ELEMENT_TYPE OttieLayer *
|
||||
#define GDK_ARRAY_FREE_FUNC g_object_unref
|
||||
#define GDK_ARRAY_TYPE_NAME OttieLayerList
|
||||
#define GDK_ARRAY_NAME ottie_layer_list
|
||||
#define GDK_ARRAY_PREALLOC 4
|
||||
#include "gdk/gdkarrayimpl.c"
|
||||
|
||||
struct _OttiePrecomp
|
||||
{
|
||||
OttieLayer parent;
|
||||
|
||||
OttieLayerList layers;
|
||||
};
|
||||
|
||||
struct _OttiePrecompClass
|
||||
{
|
||||
OttieLayerClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (OttiePrecomp, ottie_precomp, OTTIE_TYPE_LAYER)
|
||||
|
||||
static void
|
||||
ottie_precomp_snapshot (OttieLayer *layer,
|
||||
GtkSnapshot *snapshot,
|
||||
double timestamp)
|
||||
{
|
||||
OttiePrecomp *self = OTTIE_PRECOMP (layer);
|
||||
|
||||
for (gsize i = ottie_layer_list_get_size (&self->layers); i-- > 0; )
|
||||
{
|
||||
ottie_layer_snapshot (ottie_layer_list_get (&self->layers, i), snapshot, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_precomp_dispose (GObject *object)
|
||||
{
|
||||
OttiePrecomp *self = OTTIE_PRECOMP (object);
|
||||
|
||||
ottie_layer_list_clear (&self->layers);
|
||||
|
||||
G_OBJECT_CLASS (ottie_precomp_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_precomp_finalize (GObject *object)
|
||||
{
|
||||
//OttiePrecomp *self = OTTIE_PRECOMP (object);
|
||||
|
||||
G_OBJECT_CLASS (ottie_precomp_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_precomp_class_init (OttiePrecompClass *klass)
|
||||
{
|
||||
OttieLayerClass *layer_class = OTTIE_LAYER_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
layer_class->snapshot = ottie_precomp_snapshot;
|
||||
|
||||
gobject_class->finalize = ottie_precomp_finalize;
|
||||
gobject_class->dispose = ottie_precomp_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_precomp_init (OttiePrecomp *self)
|
||||
{
|
||||
ottie_layer_list_init (&self->layers);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_precomp_parse_layer (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttiePrecomp *self = data;
|
||||
OttieLayer *layer;
|
||||
int type;
|
||||
|
||||
if (!json_reader_is_object (reader))
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "Layer %zu is not an object",
|
||||
ottie_layer_list_get_size (&self->layers));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!json_reader_read_member (reader, "ty"))
|
||||
{
|
||||
ottie_parser_error_syntax (reader, "Layer %zu has no type",
|
||||
ottie_layer_list_get_size (&self->layers));
|
||||
json_reader_end_member (reader);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
type = json_reader_get_int_value (reader);
|
||||
json_reader_end_member (reader);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
layer = ottie_precomp_layer_parse (reader);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
layer = ottie_shape_layer_parse (reader);
|
||||
break;
|
||||
|
||||
default:
|
||||
ottie_parser_error_value (reader, "Layer %zu has unknown type %d",
|
||||
ottie_layer_list_get_size (&self->layers),
|
||||
type);
|
||||
layer = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (layer)
|
||||
ottie_layer_list_append (&self->layers, layer);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ottie_precomp_parse_layers (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttiePrecomp **target = (OttiePrecomp **) ((guint8 *) data + offset);
|
||||
OttiePrecomp *self;
|
||||
|
||||
self = g_object_new (OTTIE_TYPE_PRECOMP, NULL);
|
||||
|
||||
if (!ottie_parser_parse_array (reader, "layers",
|
||||
0, G_MAXUINT, NULL,
|
||||
0, 0,
|
||||
ottie_precomp_parse_layer,
|
||||
self))
|
||||
{
|
||||
g_object_unref (self);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_clear_object (target);
|
||||
*target = self;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
119
ottie/ottieprecomplayer.c
Normal file
119
ottie/ottieprecomplayer.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottieprecomplayerprivate.h"
|
||||
|
||||
#include "ottiedoublevalueprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gsk/gsk.h>
|
||||
|
||||
struct _OttiePrecompLayer
|
||||
{
|
||||
OttieLayer parent;
|
||||
|
||||
OttieDoubleValue time_map;
|
||||
|
||||
char *ref_id;
|
||||
OttieLayer *ref;
|
||||
};
|
||||
|
||||
struct _OttiePrecompLayerClass
|
||||
{
|
||||
OttieLayerClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (OttiePrecompLayer, ottie_precomp_layer, OTTIE_TYPE_LAYER)
|
||||
|
||||
static void
|
||||
ottie_precomp_layer_snapshot (OttieLayer *layer,
|
||||
GtkSnapshot *snapshot,
|
||||
double timestamp)
|
||||
{
|
||||
OttiePrecompLayer *self = OTTIE_PRECOMP_LAYER (layer);
|
||||
|
||||
if (self->ref == NULL)
|
||||
return;
|
||||
|
||||
ottie_layer_snapshot (self->ref,
|
||||
snapshot,
|
||||
ottie_double_value_get (&self->time_map, timestamp));
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_precomp_layer_dispose (GObject *object)
|
||||
{
|
||||
OttiePrecompLayer *self = OTTIE_PRECOMP_LAYER (object);
|
||||
|
||||
g_clear_object (&self->ref);
|
||||
g_clear_pointer (&self->ref_id, g_free);
|
||||
ottie_double_value_clear (&self->time_map);
|
||||
|
||||
G_OBJECT_CLASS (ottie_precomp_layer_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_precomp_layer_finalize (GObject *object)
|
||||
{
|
||||
//OttiePrecompLayer *self = OTTIE_PRECOMP_LAYER (object);
|
||||
|
||||
G_OBJECT_CLASS (ottie_precomp_layer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_precomp_layer_class_init (OttiePrecompLayerClass *klass)
|
||||
{
|
||||
OttieLayerClass *layer_class = OTTIE_LAYER_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
layer_class->snapshot = ottie_precomp_layer_snapshot;
|
||||
|
||||
gobject_class->finalize = ottie_precomp_layer_finalize;
|
||||
gobject_class->dispose = ottie_precomp_layer_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_precomp_layer_init (OttiePrecompLayer *self)
|
||||
{
|
||||
ottie_double_value_init (&self->time_map, 0);
|
||||
}
|
||||
|
||||
OttieLayer *
|
||||
ottie_precomp_layer_parse (JsonReader *reader)
|
||||
{
|
||||
OttieParserOption options[] = {
|
||||
OTTIE_PARSE_OPTIONS_LAYER
|
||||
{ "refId", ottie_parser_option_string, G_STRUCT_OFFSET (OttiePrecompLayer, ref_id) },
|
||||
{ "tm", ottie_double_value_parse, 0 },
|
||||
};
|
||||
OttiePrecompLayer *self;
|
||||
|
||||
self = g_object_new (OTTIE_TYPE_PRECOMP_LAYER, NULL);
|
||||
|
||||
if (!ottie_parser_parse_object (reader, "precomp layer", options, G_N_ELEMENTS (options), self))
|
||||
{
|
||||
g_object_unref (self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return OTTIE_LAYER (self);
|
||||
}
|
||||
|
||||
45
ottie/ottieprecomplayerprivate.h
Normal file
45
ottie/ottieprecomplayerprivate.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_PRECOMP_LAYER_PRIVATE_H__
|
||||
#define __OTTIE_PRECOMP_LAYER_PRIVATE_H__
|
||||
|
||||
#include "ottielayerprivate.h"
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OTTIE_TYPE_PRECOMP_LAYER (ottie_precomp_layer_get_type ())
|
||||
#define OTTIE_PRECOMP_LAYER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OTTIE_TYPE_PRECOMP_LAYER, OttiePrecompLayer))
|
||||
#define OTTIE_PRECOMP_LAYER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), OTTIE_TYPE_PRECOMP_LAYER, OttiePrecompLayerClass))
|
||||
#define OTTIE_IS_PRECOMP_LAYER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OTTIE_TYPE_PRECOMP_LAYER))
|
||||
#define OTTIE_IS_PRECOMP_LAYER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OTTIE_TYPE_PRECOMP_LAYER))
|
||||
#define OTTIE_PRECOMP_LAYER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OTTIE_TYPE_PRECOMP_LAYER, OttiePrecompLayerClass))
|
||||
|
||||
typedef struct _OttiePrecompLayer OttiePrecompLayer;
|
||||
typedef struct _OttiePrecompLayerClass OttiePrecompLayerClass;
|
||||
|
||||
GType ottie_precomp_layer_get_type (void) G_GNUC_CONST;
|
||||
|
||||
OttieLayer * ottie_precomp_layer_parse (JsonReader *reader);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_PRECOMP_LAYER_PRIVATE_H__ */
|
||||
47
ottie/ottieprecompprivate.h
Normal file
47
ottie/ottieprecompprivate.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_PRECOMP_PRIVATE_H__
|
||||
#define __OTTIE_PRECOMP_PRIVATE_H__
|
||||
|
||||
#include "ottielayerprivate.h"
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OTTIE_TYPE_PRECOMP (ottie_precomp_get_type ())
|
||||
#define OTTIE_PRECOMP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OTTIE_TYPE_PRECOMP, OttiePrecomp))
|
||||
#define OTTIE_PRECOMP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), OTTIE_TYPE_PRECOMP, OttiePrecompClass))
|
||||
#define OTTIE_IS_PRECOMP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OTTIE_TYPE_PRECOMP))
|
||||
#define OTTIE_IS_PRECOMP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OTTIE_TYPE_PRECOMP))
|
||||
#define OTTIE_PRECOMP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OTTIE_TYPE_PRECOMP, OttiePrecompClass))
|
||||
|
||||
typedef struct _OttiePrecomp OttiePrecomp;
|
||||
typedef struct _OttiePrecompClass OttiePrecompClass;
|
||||
|
||||
GType ottie_precomp_get_type (void) G_GNUC_CONST;
|
||||
|
||||
gboolean ottie_precomp_parse_layers (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_PRECOMP_PRIVATE_H__ */
|
||||
137
ottie/ottierectshape.c
Normal file
137
ottie/ottierectshape.c
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottierectshapeprivate.h"
|
||||
|
||||
#include "ottiedoublevalueprivate.h"
|
||||
#include "ottiepointvalueprivate.h"
|
||||
#include "ottieparserprivate.h"
|
||||
#include "ottieshapeprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
struct _OttieRectShape
|
||||
{
|
||||
OttieShape parent;
|
||||
|
||||
double direction;
|
||||
OttiePointValue position;
|
||||
OttiePointValue size;
|
||||
OttieDoubleValue rounded;
|
||||
};
|
||||
|
||||
struct _OttieRectShapeClass
|
||||
{
|
||||
OttieShapeClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (OttieRectShape, ottie_rect_shape, OTTIE_TYPE_SHAPE)
|
||||
|
||||
static void
|
||||
ottie_rect_shape_snapshot (OttieShape *shape,
|
||||
GtkSnapshot *snapshot,
|
||||
OttieShapeSnapshot *snapshot_data,
|
||||
double timestamp)
|
||||
{
|
||||
OttieRectShape *self = OTTIE_RECT_SHAPE (shape);
|
||||
graphene_point_t p, s;
|
||||
double r;
|
||||
graphene_rect_t rect;
|
||||
GskPathBuilder *builder;
|
||||
|
||||
ottie_point_value_get (&self->position, timestamp, &p);
|
||||
ottie_point_value_get (&self->size, timestamp, &s);
|
||||
r = ottie_double_value_get (&self->rounded, timestamp);
|
||||
|
||||
builder = gsk_path_builder_new ();
|
||||
rect = GRAPHENE_RECT_INIT (p.x - s.x / 2,
|
||||
p.y - s.y / 2,
|
||||
s.x, s.y);
|
||||
if (r <= 0)
|
||||
{
|
||||
gsk_path_builder_add_rect (builder, &rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
GskRoundedRect rounded;
|
||||
|
||||
gsk_rounded_rect_init_from_rect (&rounded, &rect, r);
|
||||
gsk_path_builder_add_rounded_rect (builder, &rounded);
|
||||
}
|
||||
|
||||
ottie_shape_snapshot_add_path (snapshot_data,
|
||||
gsk_path_builder_free_to_path (builder));
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_rect_shape_dispose (GObject *object)
|
||||
{
|
||||
OttieRectShape *self = OTTIE_RECT_SHAPE (object);
|
||||
|
||||
ottie_point_value_clear (&self->position);
|
||||
ottie_point_value_clear (&self->size);
|
||||
ottie_double_value_clear (&self->rounded);
|
||||
|
||||
G_OBJECT_CLASS (ottie_rect_shape_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_rect_shape_class_init (OttieRectShapeClass *klass)
|
||||
{
|
||||
OttieShapeClass *shape_class = OTTIE_SHAPE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
shape_class->snapshot = ottie_rect_shape_snapshot;
|
||||
|
||||
gobject_class->dispose = ottie_rect_shape_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_rect_shape_init (OttieRectShape *self)
|
||||
{
|
||||
ottie_point_value_init (&self->position, &GRAPHENE_POINT_INIT (0, 0));
|
||||
ottie_point_value_init (&self->size, &GRAPHENE_POINT_INIT (0, 0));
|
||||
ottie_double_value_init (&self->rounded, 0);
|
||||
}
|
||||
|
||||
OttieShape *
|
||||
ottie_rect_shape_parse (JsonReader *reader)
|
||||
{
|
||||
OttieParserOption options[] = {
|
||||
OTTIE_PARSE_OPTIONS_SHAPE
|
||||
{ "d", ottie_parser_option_double, G_STRUCT_OFFSET (OttieRectShape, direction) },
|
||||
{ "p", ottie_point_value_parse, G_STRUCT_OFFSET (OttieRectShape, position) },
|
||||
{ "s", ottie_point_value_parse, G_STRUCT_OFFSET (OttieRectShape, size) },
|
||||
{ "r", ottie_double_value_parse, G_STRUCT_OFFSET (OttieRectShape, rounded) },
|
||||
};
|
||||
OttieRectShape *self;
|
||||
|
||||
self = g_object_new (OTTIE_TYPE_RECT_SHAPE, NULL);
|
||||
|
||||
if (!ottie_parser_parse_object (reader, "rect shape", options, G_N_ELEMENTS (options), self))
|
||||
{
|
||||
g_object_unref (self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return OTTIE_SHAPE (self);
|
||||
}
|
||||
|
||||
45
ottie/ottierectshapeprivate.h
Normal file
45
ottie/ottierectshapeprivate.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_RECT_SHAPE_PRIVATE_H__
|
||||
#define __OTTIE_RECT_SHAPE_PRIVATE_H__
|
||||
|
||||
#include "ottieshapeprivate.h"
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OTTIE_TYPE_RECT_SHAPE (ottie_rect_shape_get_type ())
|
||||
#define OTTIE_RECT_SHAPE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OTTIE_TYPE_RECT_SHAPE, OttieRectShape))
|
||||
#define OTTIE_RECT_SHAPE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), OTTIE_TYPE_RECT_SHAPE, OttieRectShapeClass))
|
||||
#define OTTIE_IS_RECT_SHAPE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OTTIE_TYPE_RECT_SHAPE))
|
||||
#define OTTIE_IS_RECT_SHAPE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OTTIE_TYPE_RECT_SHAPE))
|
||||
#define OTTIE_RECT_SHAPE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OTTIE_TYPE_RECT_SHAPE, OttieRectShapeClass))
|
||||
|
||||
typedef struct _OttieRectShape OttieRectShape;
|
||||
typedef struct _OttieRectShapeClass OttieRectShapeClass;
|
||||
|
||||
GType ottie_rect_shape_get_type (void) G_GNUC_CONST;
|
||||
|
||||
OttieShape * ottie_rect_shape_parse (JsonReader *reader);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_RECT_SHAPE_PRIVATE_H__ */
|
||||
123
ottie/ottieshape.c
Normal file
123
ottie/ottieshape.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottieshapeprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
G_DEFINE_TYPE (OttieShape, ottie_shape, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
ottie_shape_dispose (GObject *object)
|
||||
{
|
||||
OttieShape *self = OTTIE_SHAPE (object);
|
||||
|
||||
g_clear_pointer (&self->name, g_free);
|
||||
g_clear_pointer (&self->match_name, g_free);
|
||||
|
||||
G_OBJECT_CLASS (ottie_shape_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_shape_finalize (GObject *object)
|
||||
{
|
||||
//OttieShape *self = OTTIE_SHAPE (object);
|
||||
|
||||
G_OBJECT_CLASS (ottie_shape_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_shape_class_init (OttieShapeClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
|
||||
gobject_class->finalize = ottie_shape_finalize;
|
||||
gobject_class->dispose = ottie_shape_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_shape_init (OttieShape *self)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ottie_shape_snapshot (OttieShape *self,
|
||||
GtkSnapshot *snapshot,
|
||||
OttieShapeSnapshot *snapshot_data,
|
||||
double timestamp)
|
||||
{
|
||||
OTTIE_SHAPE_GET_CLASS (self)->snapshot (self, snapshot, snapshot_data, timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
ottie_shape_snapshot_init (OttieShapeSnapshot *data,
|
||||
OttieShapeSnapshot *copy_from)
|
||||
{
|
||||
if (copy_from)
|
||||
{
|
||||
data->paths = g_slist_copy_deep (copy_from->paths, (GCopyFunc) gsk_path_ref, NULL);
|
||||
if (copy_from->cached_path)
|
||||
data->cached_path = gsk_path_ref (copy_from->cached_path);
|
||||
else
|
||||
data->cached_path = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset (data, 0, sizeof (OttieShapeSnapshot));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ottie_shape_snapshot_clear (OttieShapeSnapshot *data)
|
||||
{
|
||||
g_slist_free_full (data->paths, (GDestroyNotify) gsk_path_unref);
|
||||
data->paths = NULL;
|
||||
|
||||
g_clear_pointer (&data->cached_path, gsk_path_unref);
|
||||
}
|
||||
|
||||
void
|
||||
ottie_shape_snapshot_add_path (OttieShapeSnapshot *data,
|
||||
GskPath *path)
|
||||
{
|
||||
g_clear_pointer (&data->cached_path, gsk_path_unref);
|
||||
data->paths = g_slist_prepend (data->paths, path);
|
||||
}
|
||||
|
||||
GskPath *
|
||||
ottie_shape_snapshot_get_path (OttieShapeSnapshot *data)
|
||||
{
|
||||
GskPathBuilder *builder;
|
||||
GSList *l;
|
||||
|
||||
if (data->cached_path)
|
||||
return data->cached_path;
|
||||
|
||||
builder = gsk_path_builder_new ();
|
||||
for (l = data->paths; l; l = l->next)
|
||||
{
|
||||
gsk_path_builder_add_path (builder, l->data);
|
||||
}
|
||||
data->cached_path = gsk_path_builder_free_to_path (builder);
|
||||
|
||||
return data->cached_path;
|
||||
}
|
||||
|
||||
132
ottie/ottieshapelayer.c
Normal file
132
ottie/ottieshapelayer.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottieshapelayerprivate.h"
|
||||
|
||||
#include "ottiefillshapeprivate.h"
|
||||
#include "ottiegroupshapeprivate.h"
|
||||
#include "ottieparserprivate.h"
|
||||
#include "ottiepathshapeprivate.h"
|
||||
#include "ottieshapeprivate.h"
|
||||
#include "ottiestrokeshapeprivate.h"
|
||||
#include "ottietransformprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gsk/gsk.h>
|
||||
|
||||
struct _OttieShapeLayer
|
||||
{
|
||||
OttieLayer parent;
|
||||
|
||||
OttieShape *shapes;
|
||||
};
|
||||
|
||||
struct _OttieShapeLayerClass
|
||||
{
|
||||
OttieLayerClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (OttieShapeLayer, ottie_shape_layer, OTTIE_TYPE_LAYER)
|
||||
|
||||
static void
|
||||
ottie_shape_layer_snapshot (OttieLayer *layer,
|
||||
GtkSnapshot *snapshot,
|
||||
double timestamp)
|
||||
{
|
||||
OttieShapeLayer *self = OTTIE_SHAPE_LAYER (layer);
|
||||
OttieShapeSnapshot snapshot_data;
|
||||
|
||||
ottie_shape_snapshot_init (&snapshot_data, NULL);
|
||||
|
||||
ottie_shape_snapshot (self->shapes,
|
||||
snapshot,
|
||||
&snapshot_data,
|
||||
timestamp);
|
||||
|
||||
ottie_shape_snapshot_clear (&snapshot_data);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_shape_layer_dispose (GObject *object)
|
||||
{
|
||||
OttieShapeLayer *self = OTTIE_SHAPE_LAYER (object);
|
||||
|
||||
g_clear_object (&self->shapes);
|
||||
|
||||
G_OBJECT_CLASS (ottie_shape_layer_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_shape_layer_finalize (GObject *object)
|
||||
{
|
||||
//OttieShapeLayer *self = OTTIE_SHAPE_LAYER (object);
|
||||
|
||||
G_OBJECT_CLASS (ottie_shape_layer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_shape_layer_class_init (OttieShapeLayerClass *klass)
|
||||
{
|
||||
OttieLayerClass *layer_class = OTTIE_LAYER_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
layer_class->snapshot = ottie_shape_layer_snapshot;
|
||||
|
||||
gobject_class->finalize = ottie_shape_layer_finalize;
|
||||
gobject_class->dispose = ottie_shape_layer_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_shape_layer_init (OttieShapeLayer *self)
|
||||
{
|
||||
self->shapes = ottie_group_shape_new ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_shape_layer_parse_shapes (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttieShapeLayer *self = data;
|
||||
|
||||
return ottie_group_shape_parse_shapes (reader, 0, self->shapes);
|
||||
}
|
||||
|
||||
OttieLayer *
|
||||
ottie_shape_layer_parse (JsonReader *reader)
|
||||
{
|
||||
OttieParserOption options[] = {
|
||||
OTTIE_PARSE_OPTIONS_LAYER
|
||||
{ "shapes", ottie_shape_layer_parse_shapes, 0 },
|
||||
};
|
||||
OttieShapeLayer *self;
|
||||
|
||||
self = g_object_new (OTTIE_TYPE_SHAPE_LAYER, NULL);
|
||||
|
||||
if (!ottie_parser_parse_object (reader, "shape layer", options, G_N_ELEMENTS (options), self))
|
||||
{
|
||||
g_object_unref (self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return OTTIE_LAYER (self);
|
||||
}
|
||||
|
||||
45
ottie/ottieshapelayerprivate.h
Normal file
45
ottie/ottieshapelayerprivate.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_SHAPE_LAYER_PRIVATE_H__
|
||||
#define __OTTIE_SHAPE_LAYER_PRIVATE_H__
|
||||
|
||||
#include "ottielayerprivate.h"
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OTTIE_TYPE_SHAPE_LAYER (ottie_shape_layer_get_type ())
|
||||
#define OTTIE_SHAPE_LAYER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OTTIE_TYPE_SHAPE_LAYER, OttieShapeLayer))
|
||||
#define OTTIE_SHAPE_LAYER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), OTTIE_TYPE_SHAPE_LAYER, OttieShapeLayerClass))
|
||||
#define OTTIE_IS_SHAPE_LAYER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OTTIE_TYPE_SHAPE_LAYER))
|
||||
#define OTTIE_IS_SHAPE_LAYER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OTTIE_TYPE_SHAPE_LAYER))
|
||||
#define OTTIE_SHAPE_LAYER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OTTIE_TYPE_SHAPE_LAYER, OttieShapeLayerClass))
|
||||
|
||||
typedef struct _OttieShapeLayer OttieShapeLayer;
|
||||
typedef struct _OttieShapeLayerClass OttieShapeLayerClass;
|
||||
|
||||
GType ottie_shape_layer_get_type (void) G_GNUC_CONST;
|
||||
|
||||
OttieLayer * ottie_shape_layer_parse (JsonReader *reader);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_SHAPE_LAYER_PRIVATE_H__ */
|
||||
87
ottie/ottieshapeprivate.h
Normal file
87
ottie/ottieshapeprivate.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_SHAPE_PRIVATE_H__
|
||||
#define __OTTIE_SHAPE_PRIVATE_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OTTIE_TYPE_SHAPE (ottie_shape_get_type ())
|
||||
#define OTTIE_SHAPE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OTTIE_TYPE_SHAPE, OttieShape))
|
||||
#define OTTIE_SHAPE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), OTTIE_TYPE_SHAPE, OttieShapeClass))
|
||||
#define OTTIE_IS_SHAPE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OTTIE_TYPE_SHAPE))
|
||||
#define OTTIE_IS_SHAPE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OTTIE_TYPE_SHAPE))
|
||||
#define OTTIE_SHAPE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OTTIE_TYPE_SHAPE, OttieShapeClass))
|
||||
|
||||
typedef struct _OttieShapeSnapshot OttieShapeSnapshot;
|
||||
typedef struct _OttieShape OttieShape;
|
||||
typedef struct _OttieShapeClass OttieShapeClass;
|
||||
|
||||
struct _OttieShapeSnapshot
|
||||
{
|
||||
GSList *paths;
|
||||
GskPath *cached_path;
|
||||
};
|
||||
|
||||
struct _OttieShape
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
char *name;
|
||||
char *match_name;
|
||||
gboolean hidden;
|
||||
};
|
||||
|
||||
struct _OttieShapeClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* snapshot) (OttieShape *self,
|
||||
GtkSnapshot *snapshot,
|
||||
OttieShapeSnapshot *snapshot_data,
|
||||
double timestamp);
|
||||
};
|
||||
|
||||
GType ottie_shape_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void ottie_shape_snapshot (OttieShape *self,
|
||||
GtkSnapshot *snapshot,
|
||||
OttieShapeSnapshot *snapshot_data,
|
||||
double timestamp);
|
||||
|
||||
|
||||
void ottie_shape_snapshot_init (OttieShapeSnapshot *data,
|
||||
OttieShapeSnapshot *copy_from);
|
||||
void ottie_shape_snapshot_clear (OttieShapeSnapshot *data);
|
||||
void ottie_shape_snapshot_add_path (OttieShapeSnapshot *data,
|
||||
GskPath *path);
|
||||
GskPath * ottie_shape_snapshot_get_path (OttieShapeSnapshot *data);
|
||||
|
||||
#define OTTIE_PARSE_OPTIONS_SHAPE \
|
||||
{ "nm", ottie_parser_option_string, G_STRUCT_OFFSET (OttieShape, name) }, \
|
||||
{ "mn", ottie_parser_option_string, G_STRUCT_OFFSET (OttieShape, match_name) }, \
|
||||
{ "hd", ottie_parser_option_boolean, G_STRUCT_OFFSET (OttieShape, hidden) }, \
|
||||
{ "ix", ottie_parser_option_skip_index, 0 }, \
|
||||
{ "ty", ottie_parser_option_skip, 0 },
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_SHAPE_PRIVATE_H__ */
|
||||
155
ottie/ottiestrokeshape.c
Normal file
155
ottie/ottiestrokeshape.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottiestrokeshapeprivate.h"
|
||||
|
||||
#include "ottiecolorvalueprivate.h"
|
||||
#include "ottiedoublevalueprivate.h"
|
||||
#include "ottieparserprivate.h"
|
||||
#include "ottieshapeprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gsk/gsk.h>
|
||||
|
||||
struct _OttieStrokeShape
|
||||
{
|
||||
OttieShape parent;
|
||||
|
||||
OttieDoubleValue opacity;
|
||||
OttieColorValue color;
|
||||
OttieDoubleValue line_width;
|
||||
GskLineCap line_cap;
|
||||
GskLineJoin line_join;
|
||||
double miter_limit;
|
||||
GskBlendMode blend_mode;
|
||||
};
|
||||
|
||||
struct _OttieStrokeShapeClass
|
||||
{
|
||||
OttieShapeClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (OttieStrokeShape, ottie_stroke_shape, OTTIE_TYPE_SHAPE)
|
||||
|
||||
static void
|
||||
ottie_stroke_shape_snapshot (OttieShape *shape,
|
||||
GtkSnapshot *snapshot,
|
||||
OttieShapeSnapshot *snapshot_data,
|
||||
double timestamp)
|
||||
{
|
||||
OttieStrokeShape *self = OTTIE_STROKE_SHAPE (shape);
|
||||
GskPath *path;
|
||||
graphene_rect_t bounds;
|
||||
GdkRGBA color;
|
||||
GskStroke *stroke;
|
||||
double opacity, line_width;
|
||||
|
||||
line_width = ottie_double_value_get (&self->line_width, timestamp);
|
||||
if (line_width <= 0)
|
||||
return;
|
||||
|
||||
opacity = ottie_double_value_get (&self->opacity, timestamp);
|
||||
opacity = CLAMP (opacity, 0, 100);
|
||||
ottie_color_value_get (&self->color, timestamp, &color);
|
||||
color.alpha = color.alpha * opacity / 100.f;
|
||||
if (gdk_rgba_is_clear (&color))
|
||||
return;
|
||||
|
||||
path = ottie_shape_snapshot_get_path (snapshot_data);
|
||||
stroke = gsk_stroke_new (line_width);
|
||||
gsk_stroke_set_line_cap (stroke, self->line_cap);
|
||||
gsk_stroke_set_line_join (stroke, self->line_join);
|
||||
gsk_stroke_set_miter_limit (stroke, self->miter_limit);
|
||||
gtk_snapshot_push_stroke (snapshot, path, stroke);
|
||||
|
||||
gsk_path_get_stroke_bounds (path, stroke, &bounds);
|
||||
gtk_snapshot_append_color (snapshot, &color, &bounds);
|
||||
|
||||
gsk_stroke_free (stroke);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_stroke_shape_dispose (GObject *object)
|
||||
{
|
||||
OttieStrokeShape *self = OTTIE_STROKE_SHAPE (object);
|
||||
|
||||
ottie_double_value_clear (&self->opacity);
|
||||
ottie_color_value_clear (&self->color);
|
||||
ottie_double_value_clear (&self->line_width);
|
||||
|
||||
G_OBJECT_CLASS (ottie_stroke_shape_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_stroke_shape_finalize (GObject *object)
|
||||
{
|
||||
//OttieStrokeShape *self = OTTIE_STROKE_SHAPE (object);
|
||||
|
||||
G_OBJECT_CLASS (ottie_stroke_shape_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_stroke_shape_class_init (OttieStrokeShapeClass *klass)
|
||||
{
|
||||
OttieShapeClass *shape_class = OTTIE_SHAPE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
shape_class->snapshot = ottie_stroke_shape_snapshot;
|
||||
|
||||
gobject_class->finalize = ottie_stroke_shape_finalize;
|
||||
gobject_class->dispose = ottie_stroke_shape_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_stroke_shape_init (OttieStrokeShape *self)
|
||||
{
|
||||
ottie_double_value_init (&self->opacity, 100);
|
||||
ottie_color_value_init (&self->color, &(GdkRGBA) { 0, 0, 0, 1 });
|
||||
ottie_double_value_init (&self->line_width, 1);
|
||||
}
|
||||
|
||||
OttieShape *
|
||||
ottie_stroke_shape_parse (JsonReader *reader)
|
||||
{
|
||||
OttieParserOption options[] = {
|
||||
OTTIE_PARSE_OPTIONS_SHAPE
|
||||
{ "w", ottie_double_value_parse, G_STRUCT_OFFSET (OttieStrokeShape, line_width) },
|
||||
{ "o", ottie_double_value_parse, G_STRUCT_OFFSET (OttieStrokeShape, opacity) },
|
||||
{ "c", ottie_color_value_parse, G_STRUCT_OFFSET (OttieStrokeShape, color) },
|
||||
{ "lc", ottie_parser_option_line_cap, G_STRUCT_OFFSET (OttieStrokeShape, line_cap) },
|
||||
{ "lj", ottie_parser_option_line_join, G_STRUCT_OFFSET (OttieStrokeShape, line_join) },
|
||||
{ "ml", ottie_parser_option_double, G_STRUCT_OFFSET (OttieStrokeShape, miter_limit) },
|
||||
{ "bm", ottie_parser_option_blend_mode, G_STRUCT_OFFSET (OttieStrokeShape, blend_mode) },
|
||||
};
|
||||
OttieStrokeShape *self;
|
||||
|
||||
self = g_object_new (OTTIE_TYPE_STROKE_SHAPE, NULL);
|
||||
|
||||
if (!ottie_parser_parse_object (reader, "stroke shape", options, G_N_ELEMENTS (options), self))
|
||||
{
|
||||
g_object_unref (self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return OTTIE_SHAPE (self);
|
||||
}
|
||||
|
||||
45
ottie/ottiestrokeshapeprivate.h
Normal file
45
ottie/ottiestrokeshapeprivate.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_STROKE_SHAPE_PRIVATE_H__
|
||||
#define __OTTIE_STROKE_SHAPE_PRIVATE_H__
|
||||
|
||||
#include "ottieshapeprivate.h"
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OTTIE_TYPE_STROKE_SHAPE (ottie_stroke_shape_get_type ())
|
||||
#define OTTIE_STROKE_SHAPE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OTTIE_TYPE_STROKE_SHAPE, OttieStrokeShape))
|
||||
#define OTTIE_STROKE_SHAPE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), OTTIE_TYPE_STROKE_SHAPE, OttieStrokeShapeClass))
|
||||
#define OTTIE_IS_STROKE_SHAPE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OTTIE_TYPE_STROKE_SHAPE))
|
||||
#define OTTIE_IS_STROKE_SHAPE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OTTIE_TYPE_STROKE_SHAPE))
|
||||
#define OTTIE_STROKE_SHAPE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OTTIE_TYPE_STROKE_SHAPE, OttieStrokeShapeClass))
|
||||
|
||||
typedef struct _OttieStrokeShape OttieStrokeShape;
|
||||
typedef struct _OttieStrokeShapeClass OttieStrokeShapeClass;
|
||||
|
||||
GType ottie_stroke_shape_get_type (void) G_GNUC_CONST;
|
||||
|
||||
OttieShape * ottie_stroke_shape_parse (JsonReader *reader);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_STROKE_SHAPE_PRIVATE_H__ */
|
||||
182
ottie/ottietransform.c
Normal file
182
ottie/ottietransform.c
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottietransformprivate.h"
|
||||
|
||||
#include "ottiedoublevalueprivate.h"
|
||||
#include "ottieparserprivate.h"
|
||||
#include "ottiepoint3dvalueprivate.h"
|
||||
#include "ottieshapeprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gsk/gsk.h>
|
||||
|
||||
struct _OttieTransform
|
||||
{
|
||||
OttieShape parent;
|
||||
|
||||
OttieDoubleValue opacity;
|
||||
OttieDoubleValue rotation;
|
||||
OttieDoubleValue skew;
|
||||
OttieDoubleValue skew_angle;
|
||||
OttiePoint3DValue anchor;
|
||||
OttiePoint3DValue position;
|
||||
OttiePoint3DValue scale;
|
||||
};
|
||||
|
||||
struct _OttieTransformClass
|
||||
{
|
||||
OttieShapeClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (OttieTransform, ottie_transform, OTTIE_TYPE_SHAPE)
|
||||
|
||||
static void
|
||||
ottie_transform_snapshot (OttieShape *shape,
|
||||
GtkSnapshot *snapshot,
|
||||
OttieShapeSnapshot *snapshot_data,
|
||||
double timestamp)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_transform_dispose (GObject *object)
|
||||
{
|
||||
OttieTransform *self = OTTIE_TRANSFORM (object);
|
||||
|
||||
ottie_double_value_clear (&self->opacity);
|
||||
ottie_double_value_clear (&self->rotation);
|
||||
ottie_double_value_clear (&self->skew);
|
||||
ottie_double_value_clear (&self->skew_angle);
|
||||
ottie_point3d_value_clear (&self->anchor);
|
||||
ottie_point3d_value_clear (&self->position);
|
||||
ottie_point3d_value_clear (&self->scale);
|
||||
|
||||
G_OBJECT_CLASS (ottie_transform_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_transform_finalize (GObject *object)
|
||||
{
|
||||
//OttieTransform *self = OTTIE_TRANSFORM (object);
|
||||
|
||||
G_OBJECT_CLASS (ottie_transform_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_transform_class_init (OttieTransformClass *klass)
|
||||
{
|
||||
OttieShapeClass *shape_class = OTTIE_SHAPE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
shape_class->snapshot = ottie_transform_snapshot;
|
||||
|
||||
gobject_class->finalize = ottie_transform_finalize;
|
||||
gobject_class->dispose = ottie_transform_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_transform_init (OttieTransform *self)
|
||||
{
|
||||
ottie_double_value_init (&self->opacity, 100);
|
||||
ottie_double_value_init (&self->rotation, 0);
|
||||
ottie_double_value_init (&self->skew, 0);
|
||||
ottie_double_value_init (&self->skew_angle, 0);
|
||||
ottie_point3d_value_init (&self->anchor, &GRAPHENE_POINT3D_INIT (0, 0, 0));
|
||||
ottie_point3d_value_init (&self->position, &GRAPHENE_POINT3D_INIT (0, 0, 0));
|
||||
ottie_point3d_value_init (&self->scale, &GRAPHENE_POINT3D_INIT (100, 100, 100));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_transform_value_parse_point (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
return ottie_point3d_value_parse (reader, 0, offset, data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_transform_value_parse_scale (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
return ottie_point3d_value_parse (reader, 100, offset, data);
|
||||
}
|
||||
|
||||
|
||||
OttieShape *
|
||||
ottie_transform_parse (JsonReader *reader)
|
||||
{
|
||||
OttieParserOption options[] = {
|
||||
OTTIE_PARSE_OPTIONS_SHAPE
|
||||
{ "o", ottie_double_value_parse, G_STRUCT_OFFSET (OttieTransform, opacity) },
|
||||
{ "r", ottie_double_value_parse, G_STRUCT_OFFSET (OttieTransform, rotation) },
|
||||
{ "a", ottie_transform_value_parse_point, G_STRUCT_OFFSET (OttieTransform, anchor) },
|
||||
{ "p", ottie_transform_value_parse_point, G_STRUCT_OFFSET (OttieTransform, position) },
|
||||
{ "s", ottie_transform_value_parse_scale, G_STRUCT_OFFSET (OttieTransform, scale) },
|
||||
{ "sk", ottie_double_value_parse, G_STRUCT_OFFSET (OttieTransform, skew) },
|
||||
{ "sa", ottie_double_value_parse, G_STRUCT_OFFSET (OttieTransform, skew_angle) },
|
||||
};
|
||||
OttieTransform *self;
|
||||
|
||||
self = g_object_new (OTTIE_TYPE_TRANSFORM, NULL);
|
||||
|
||||
if (!ottie_parser_parse_object (reader, "transform", options, G_N_ELEMENTS (options), self))
|
||||
{
|
||||
g_object_unref (self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return OTTIE_SHAPE (self);
|
||||
}
|
||||
|
||||
GskTransform *
|
||||
ottie_transform_get_transform (OttieTransform *self,
|
||||
double timestamp)
|
||||
{
|
||||
graphene_point3d_t anchor, position, scale;
|
||||
GskTransform *transform;
|
||||
double skew, skew_angle;
|
||||
|
||||
ottie_point3d_value_get (&self->anchor, timestamp, &anchor);
|
||||
ottie_point3d_value_get (&self->position, timestamp, &position);
|
||||
ottie_point3d_value_get (&self->scale, timestamp, &scale);
|
||||
|
||||
transform = NULL;
|
||||
transform = gsk_transform_translate_3d (transform, &position);
|
||||
transform = gsk_transform_rotate (transform, ottie_double_value_get (&self->rotation, timestamp));
|
||||
skew = ottie_double_value_get (&self->skew, timestamp);
|
||||
if (skew)
|
||||
{
|
||||
graphene_matrix_t matrix;
|
||||
skew_angle = ottie_double_value_get (&self->skew_angle, timestamp);
|
||||
transform = gsk_transform_rotate (transform, -skew_angle);
|
||||
graphene_matrix_init_skew (&matrix, -skew / 180.0 * G_PI, 0);
|
||||
transform = gsk_transform_matrix (transform, &matrix);
|
||||
transform = gsk_transform_rotate (transform, skew_angle);
|
||||
}
|
||||
transform = gsk_transform_scale_3d (transform, scale.x / 100, scale.y / 100, scale.z / 100);
|
||||
graphene_point3d_scale (&anchor, -1, &anchor);
|
||||
transform = gsk_transform_translate_3d (transform, &anchor);
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
48
ottie/ottietransformprivate.h
Normal file
48
ottie/ottietransformprivate.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_TRANSFORM_PRIVATE_H__
|
||||
#define __OTTIE_TRANSFORM_PRIVATE_H__
|
||||
|
||||
#include "ottieshapeprivate.h"
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OTTIE_TYPE_TRANSFORM (ottie_transform_get_type ())
|
||||
#define OTTIE_TRANSFORM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OTTIE_TYPE_TRANSFORM, OttieTransform))
|
||||
#define OTTIE_TRANSFORM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), OTTIE_TYPE_TRANSFORM, OttieTransformClass))
|
||||
#define OTTIE_IS_TRANSFORM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OTTIE_TYPE_TRANSFORM))
|
||||
#define OTTIE_IS_TRANSFORM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OTTIE_TYPE_TRANSFORM))
|
||||
#define OTTIE_TRANSFORM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OTTIE_TYPE_TRANSFORM, OttieTransformClass))
|
||||
|
||||
typedef struct _OttieTransform OttieTransform;
|
||||
typedef struct _OttieTransformClass OttieTransformClass;
|
||||
|
||||
GType ottie_transform_get_type (void) G_GNUC_CONST;
|
||||
|
||||
OttieShape * ottie_transform_parse (JsonReader *reader);
|
||||
|
||||
GskTransform * ottie_transform_get_transform (OttieTransform *self,
|
||||
double timestamp);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_TRANSFORM_PRIVATE_H__ */
|
||||
198
ottie/ottietrimshape.c
Normal file
198
ottie/ottietrimshape.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottietrimshapeprivate.h"
|
||||
|
||||
#include "ottiedoublevalueprivate.h"
|
||||
#include "ottieparserprivate.h"
|
||||
#include "ottieshapeprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gsk/gsk.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
OTTIE_TRIM_TOGETHER,
|
||||
OTTIE_TRIM_SEPARATELY
|
||||
} OttieTrimMode;
|
||||
|
||||
struct _OttieTrimShape
|
||||
{
|
||||
OttieShape parent;
|
||||
|
||||
OttieTrimMode mode;
|
||||
OttieDoubleValue start;
|
||||
OttieDoubleValue end;
|
||||
OttieDoubleValue offset;
|
||||
};
|
||||
|
||||
struct _OttieTrimShapeClass
|
||||
{
|
||||
OttieShapeClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (OttieTrimShape, ottie_trim_shape, OTTIE_TYPE_SHAPE)
|
||||
|
||||
static void
|
||||
ottie_trim_shape_snapshot (OttieShape *shape,
|
||||
GtkSnapshot *snapshot,
|
||||
OttieShapeSnapshot *snapshot_data,
|
||||
double timestamp)
|
||||
{
|
||||
OttieTrimShape *self = OTTIE_TRIM_SHAPE (shape);
|
||||
GskPathMeasure *measure;
|
||||
GskPath *path;
|
||||
GskPathBuilder *builder;
|
||||
double start, end, offset;
|
||||
|
||||
path = ottie_shape_snapshot_get_path (snapshot_data);
|
||||
measure = gsk_path_measure_new (path);
|
||||
start = ottie_double_value_get (&self->start, timestamp);
|
||||
start = CLAMP (start, 0, 100) / 100.f;
|
||||
end = ottie_double_value_get (&self->end, timestamp);
|
||||
end = CLAMP (end, 0, 100) / 100.f;
|
||||
|
||||
builder = gsk_path_builder_new ();
|
||||
if (start != end)
|
||||
{
|
||||
if (start > end)
|
||||
{
|
||||
double swap = end;
|
||||
end = start;
|
||||
start = swap;
|
||||
}
|
||||
offset = ottie_double_value_get (&self->offset, timestamp) / 360.f;
|
||||
start += offset;
|
||||
start = start - floor (start);
|
||||
start *= gsk_path_measure_get_length (measure);
|
||||
end += offset;
|
||||
end = end - floor (end);
|
||||
end *= gsk_path_measure_get_length (measure);
|
||||
|
||||
gsk_path_builder_add_segment (builder, measure, start, end);
|
||||
}
|
||||
path = gsk_path_builder_free_to_path (builder);
|
||||
|
||||
ottie_shape_snapshot_clear (snapshot_data);
|
||||
ottie_shape_snapshot_add_path (snapshot_data, path);
|
||||
|
||||
gsk_path_measure_unref (measure);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_trim_shape_dispose (GObject *object)
|
||||
{
|
||||
OttieTrimShape *self = OTTIE_TRIM_SHAPE (object);
|
||||
|
||||
ottie_double_value_clear (&self->start);
|
||||
ottie_double_value_clear (&self->end);
|
||||
ottie_double_value_clear (&self->offset);
|
||||
|
||||
G_OBJECT_CLASS (ottie_trim_shape_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_trim_shape_finalize (GObject *object)
|
||||
{
|
||||
//OttieTrimShape *self = OTTIE_TRIM_SHAPE (object);
|
||||
|
||||
G_OBJECT_CLASS (ottie_trim_shape_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_trim_shape_class_init (OttieTrimShapeClass *klass)
|
||||
{
|
||||
OttieShapeClass *shape_class = OTTIE_SHAPE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
shape_class->snapshot = ottie_trim_shape_snapshot;
|
||||
|
||||
gobject_class->finalize = ottie_trim_shape_finalize;
|
||||
gobject_class->dispose = ottie_trim_shape_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_trim_shape_init (OttieTrimShape *self)
|
||||
{
|
||||
ottie_double_value_init (&self->start, 0);
|
||||
ottie_double_value_init (&self->end, 100);
|
||||
ottie_double_value_init (&self->offset, 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ottie_trim_mode_parse (JsonReader *reader,
|
||||
gsize offset,
|
||||
gpointer data)
|
||||
{
|
||||
OttieTrimMode trim_mode;
|
||||
gint64 i;
|
||||
|
||||
i = json_reader_get_int_value (reader);
|
||||
if (json_reader_get_error (reader))
|
||||
{
|
||||
ottie_parser_emit_error (reader, json_reader_get_error (reader));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
trim_mode = OTTIE_TRIM_TOGETHER;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ottie_parser_error_unsupported (reader, "Figure out separate trim mode");
|
||||
trim_mode = OTTIE_TRIM_SEPARATELY;
|
||||
break;
|
||||
|
||||
default:
|
||||
ottie_parser_error_value (reader, "%"G_GINT64_FORMAT" is not a known trim mode", i);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*(OttieTrimMode *) ((guint8 *) data + offset) = trim_mode;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
OttieShape *
|
||||
ottie_trim_shape_parse (JsonReader *reader)
|
||||
{
|
||||
OttieParserOption options[] = {
|
||||
OTTIE_PARSE_OPTIONS_SHAPE
|
||||
{ "s", ottie_double_value_parse, G_STRUCT_OFFSET (OttieTrimShape, start) },
|
||||
{ "e", ottie_double_value_parse, G_STRUCT_OFFSET (OttieTrimShape, end) },
|
||||
{ "o", ottie_double_value_parse, G_STRUCT_OFFSET (OttieTrimShape, offset) },
|
||||
{ "m", ottie_trim_mode_parse, G_STRUCT_OFFSET (OttieTrimShape, mode) },
|
||||
};
|
||||
OttieTrimShape *self;
|
||||
|
||||
self = g_object_new (OTTIE_TYPE_TRIM_SHAPE, NULL);
|
||||
|
||||
if (!ottie_parser_parse_object (reader, "trim shape", options, G_N_ELEMENTS (options), self))
|
||||
{
|
||||
g_object_unref (self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return OTTIE_SHAPE (self);
|
||||
}
|
||||
|
||||
45
ottie/ottietrimshapeprivate.h
Normal file
45
ottie/ottietrimshapeprivate.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_TRIM_SHAPE_PRIVATE_H__
|
||||
#define __OTTIE_TRIM_SHAPE_PRIVATE_H__
|
||||
|
||||
#include "ottieshapeprivate.h"
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OTTIE_TYPE_TRIM_SHAPE (ottie_trim_shape_get_type ())
|
||||
#define OTTIE_TRIM_SHAPE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OTTIE_TYPE_TRIM_SHAPE, OttieTrimShape))
|
||||
#define OTTIE_TRIM_SHAPE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), OTTIE_TYPE_TRIM_SHAPE, OttieTrimShapeClass))
|
||||
#define OTTIE_IS_TRIM_SHAPE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OTTIE_TYPE_TRIM_SHAPE))
|
||||
#define OTTIE_IS_TRIM_SHAPE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OTTIE_TYPE_TRIM_SHAPE))
|
||||
#define OTTIE_TRIM_SHAPE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OTTIE_TYPE_TRIM_SHAPE, OttieTrimShapeClass))
|
||||
|
||||
typedef struct _OttieTrimShape OttieTrimShape;
|
||||
typedef struct _OttieTrimShapeClass OttieTrimShapeClass;
|
||||
|
||||
GType ottie_trim_shape_get_type (void) G_GNUC_CONST;
|
||||
|
||||
OttieShape * ottie_trim_shape_parse (JsonReader *reader);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __OTTIE_TRIM_SHAPE_PRIVATE_H__ */
|
||||
133
ottie/ottievalueimpl.c
Normal file
133
ottie/ottievalueimpl.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifndef OTTIE_VALUE_TYPE_NAME
|
||||
#define OTTIE_VALUE_TYPE_NAME OttieValue
|
||||
#endif
|
||||
|
||||
#ifndef OTTIE_VALUE_NAME
|
||||
#define OTTIE_VALUE_NAME ottie_value
|
||||
#endif
|
||||
|
||||
#ifndef OTTIE_VALUE_ELEMENT_TYPE
|
||||
#define OTTIE_VALUE_ELEMENT_TYPE gpointer
|
||||
#endif
|
||||
|
||||
/* make this readable */
|
||||
#define _T_ OTTIE_VALUE_ELEMENT_TYPE
|
||||
#define OttieValue OTTIE_VALUE_TYPE_NAME
|
||||
#define ottie_value_paste_more(OTTIE_VALUE_NAME, func_name) OTTIE_VALUE_NAME ## _ ## func_name
|
||||
#define ottie_value_paste(OTTIE_VALUE_NAME, func_name) ottie_value_paste_more (OTTIE_VALUE_NAME, func_name)
|
||||
#define ottie_value(func_name) ottie_value_paste (OTTIE_VALUE_NAME, func_name)
|
||||
|
||||
typedef struct OttieValue OttieValue;
|
||||
|
||||
struct OttieValue
|
||||
{
|
||||
enum {
|
||||
STATIC,
|
||||
KEYFRAMES
|
||||
} type;
|
||||
union {
|
||||
_T_ static_value;
|
||||
struct {
|
||||
_T_ *values;
|
||||
gsize n_frames;
|
||||
} keyframes;
|
||||
};
|
||||
|
||||
void
|
||||
ottie_value(init) (OttieValue *self)
|
||||
{
|
||||
memset (self, 0, sizeof (OttieValue));
|
||||
}
|
||||
|
||||
static inline void
|
||||
ottie_value(free_item) (_T_ *item)
|
||||
{
|
||||
#ifdef OTTIE_VALUE_FREE_FUNC
|
||||
#ifdef OTTIE_VALUE_BY_VALUE
|
||||
OTTIE_VALUE_FREE_FUNC (item);
|
||||
#else
|
||||
OTTIE_VALUE_FREE_FUNC (*item);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ottie_value(clear) (OttieValue *self)
|
||||
{
|
||||
#ifdef OTTIE_VALUE_FREE_FUNC
|
||||
gsize i;
|
||||
|
||||
if (self->type == STATIC)
|
||||
{
|
||||
ottie_value(free_item) (&self->static_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < self->n_values, i++)
|
||||
ottie_value(free_item) (&self->values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OTTIE_VALUE_BY_VALUE
|
||||
_T_ *
|
||||
#else
|
||||
_T_
|
||||
#endif
|
||||
ottie_value(get) (const OttieValue *self,
|
||||
double progress)
|
||||
{
|
||||
_T_ * result;
|
||||
|
||||
if (self->type == STATIC)
|
||||
{
|
||||
result = &self->static_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = &self->values[progress * self->n_values];
|
||||
}
|
||||
|
||||
#ifdef OTTIE_VALUE_BY_VALUE
|
||||
return result;
|
||||
#else
|
||||
return *result;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef OTTIE_VALUE_NO_UNDEF
|
||||
|
||||
#undef _T_
|
||||
#undef OttieValue
|
||||
#undef ottie_value_paste_more
|
||||
#undef ottie_value_paste
|
||||
#undef ottie_value
|
||||
|
||||
#undef OTTIE_VALUE_BY_VALUE
|
||||
#undef OTTIE_VALUE_ELEMENT_TYPE
|
||||
#undef OTTIE_VALUE_FREE_FUNC
|
||||
#undef OTTIE_VALUE_NAME
|
||||
#undef OTTIE_VALUE_TYPE_NAME
|
||||
#endif
|
||||
@@ -1,17 +1,18 @@
|
||||
gtk_tests = [
|
||||
# testname, optional extra sources
|
||||
['animated-resizing', ['frame-stats.c', 'variable.c']],
|
||||
['animated-revealing', ['frame-stats.c', 'variable.c']],
|
||||
['blur-performance', ['../gsk/gskcairoblur.c']],
|
||||
['motion-compression'],
|
||||
['ottie'],
|
||||
['overlayscroll'],
|
||||
['testupload'],
|
||||
['testtransform'],
|
||||
['testdropdown'],
|
||||
['rendernode'],
|
||||
['rendernode-create-tests'],
|
||||
['overlayscroll'],
|
||||
['syncscroll'],
|
||||
['animated-resizing', ['frame-stats.c', 'variable.c']],
|
||||
['animated-revealing', ['frame-stats.c', 'variable.c']],
|
||||
['motion-compression'],
|
||||
['scrolling-performance', ['frame-stats.c', 'variable.c']],
|
||||
['blur-performance', ['../gsk/gskcairoblur.c']],
|
||||
['simple'],
|
||||
['video-timer', ['variable.c']],
|
||||
['testaccel'],
|
||||
|
||||
98
tests/ottie.c
Normal file
98
tests/ottie.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <ottie/ottie.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_GNUC_UNUSED static gboolean
|
||||
save_paintable (GdkPaintable *paintable,
|
||||
const char *filename)
|
||||
{
|
||||
GtkSnapshot *snapshot;
|
||||
GskRenderNode *node;
|
||||
int width, height;
|
||||
cairo_t *cr;
|
||||
cairo_surface_t *surface;
|
||||
gboolean result;
|
||||
|
||||
width = gdk_paintable_get_intrinsic_width (paintable);
|
||||
height = gdk_paintable_get_intrinsic_height (paintable);
|
||||
|
||||
snapshot = gtk_snapshot_new ();
|
||||
gdk_paintable_snapshot (paintable, snapshot, width, height);
|
||||
node = gtk_snapshot_free_to_node (snapshot);
|
||||
if (!gsk_render_node_write_to_file (node, "foo.node", NULL))
|
||||
return FALSE;
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
|
||||
cr = cairo_create (surface);
|
||||
gsk_render_node_draw (node, cr);
|
||||
cairo_destroy (cr);
|
||||
gsk_render_node_unref (node);
|
||||
|
||||
result = cairo_surface_write_to_png (surface, filename) == CAIRO_STATUS_SUCCESS;
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GtkWidget *window, *video;
|
||||
OttiePlayer *player;
|
||||
|
||||
gtk_init ();
|
||||
|
||||
if (argc > 1)
|
||||
player = ottie_player_new_for_filename (argv[1]);
|
||||
else
|
||||
player = ottie_player_new ();
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Ottie");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
|
||||
g_signal_connect (window, "destroy", G_CALLBACK (gtk_window_destroy), NULL);
|
||||
|
||||
video = gtk_video_new ();
|
||||
gtk_video_set_loop (GTK_VIDEO (video), TRUE);
|
||||
gtk_video_set_autoplay (GTK_VIDEO (video), TRUE);
|
||||
gtk_video_set_media_stream (GTK_VIDEO (video), GTK_MEDIA_STREAM (player));
|
||||
gtk_window_set_child (GTK_WINDOW (window), video);
|
||||
|
||||
gtk_widget_show (window);
|
||||
|
||||
while (g_list_model_get_n_items (gtk_window_get_toplevels ()) > 0)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
#if 0
|
||||
for (int i = 0; i < 62; i++)
|
||||
{
|
||||
ottie_paintable_set_timestamp (paintable, i * G_USEC_PER_SEC / 30);
|
||||
save_paintable (GDK_PAINTABLE (paintable), g_strdup_printf ("foo%u.png", i));
|
||||
}
|
||||
#else
|
||||
//save_paintable (GDK_PAINTABLE (paintable), "foo.png");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user