/* * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "applib/graphics/gdraw_command_image.h" #include "applib/graphics/gdraw_command_sequence.h" #include "applib/ui/animation_timing.h" #include "util/math_fixed.h" // GDraw Command Transforms is a collection of draw command transforms. // // Some transforms apply effects immediately and others are to be used in an animation. // Transforms that are for animation and take a normalized position use the infinitive "to" as // opposed to "animation" for brevity. // // Among the animation transforms, there is class that delays the animation for each of its // participants with different delay times. These transforms are suffixed with "segmented" and // generally time the points by using a combination of GPointIndexLookup and // animation_timing_segmented. //! GStrokeWidthOp specifies the different types of operations to perform during a stroke //! width transform. Stroke width transformation takes a start and an end, so combining two //! operators can result in your desired animation. Each operation is paired with a value to //! operate along with the native stroke width. For example, if you want to start from a circle //! of diameter 10px and transform to 2x the native stroke width, start with GStrokeWidthOpSet of 10 //! and end with GStrokeWidthOpMultiply of 2. typedef enum { //! Sets the stroke width to the paired operation value, overriding the native stroke width GStrokeWidthOpSet, //! Multiplies the native stroke width with the paired operation value, scaling the stroke width GStrokeWidthOpMultiply, //! Adds the paired operation value to the native stroke width GStrokeWidthOpAdd, } GStrokeWidthOp; //! A GPointIndexLookup is used for segmented animations. //! Segmented animations are where participating elements have a delayed start compared to other //! elements in the same animation. Each element has the same animation time, so earlier elements //! complete their animation sooner than others. //! GPointIndexLookup is a lookup array with the mapping (GPoint index => animation index). //! The animation index is used as the delay multiple in segmented animations. //! The delay multiple is how many delay segments the particular GPoint must wait before it is //! transformed. //! @see animation_timing_segmented typedef struct { uint16_t max_index; uint16_t num_points; uint16_t index_lookup[]; } GPointIndexLookup; //! Scales a list from one size to another void gdraw_command_list_scale(GDrawCommandList *list, GSize from, GSize to); //! Scales an image to a given size void gdraw_command_image_scale(GDrawCommandImage *image, GSize to); //! Attracts points of a list to a square void gdraw_command_list_attract_to_square(GDrawCommandList *list, GSize size, int32_t normalized); //! Attracts points of an image to a square void gdraw_command_image_attract_to_square(GDrawCommandImage *image, int32_t normalized); GPoint gpoint_attract_to_square(GPoint point, GSize size, int32_t normalized); //! Creates a GPointIndexLookup based on the angle to the center of an image //! Points in the image whose ray with the image's center has a smaller angle are animated first. //! @param angle Angle at which to consider zero. Points at this angle animate first. //! @see GPointIndexLookup GPointIndexLookup *gdraw_command_list_create_index_lookup_by_angle(GDrawCommandList *list, GPoint origin, int32_t angle); //! Creates a GPointIndexLookup based on distance to a target GPoint. //! Points in the image that are closer to the target are given the lowest animation index and //! are therefore animated first. //! To obtain a stretching animation, select a target among the points in a image's perimeter that //! is most closest to its destination animation point. //! Choosing a target in the image's perimeter opposite of the destination animation point results //! in a paper flipping effect. //! @param target Point to compare against in image coordinates. (0, 0) is top left. //! @see GPointIndexLookup GPointIndexLookup *gdraw_command_list_create_index_lookup_by_distance(GDrawCommandList *list, GPoint target); //! Shifts the delay index of all points at or above a given delay index. //! \note This shifts the delay index up, so be sure to insert the last most delays first. //! @param lookup GPointIndexLookup to add delay to //! @param index Delay index to add delay to //! @param amount Amount of delay to add in index units //! @see GPointIndexLookup void gpoint_index_lookup_add_at(GPointIndexLookup *lookup, int delay_index, int delay_amount); //! Adds delay between the groups that the lookup is desired to be partitioned into. The groups //! are partitioned evenly by number of points. //! @param lookup GPointIndexLookup to add delay to //! @param num_groups Number of groups to partition by //! @param group_delay Amount of additional delay to add between each group proportional to the //! animation duration of one group //! @see GPointIndexLookup void gpoint_index_lookup_set_groups(GPointIndexLookup *lookup, int num_groups, Fixed_S32_16 group_delay); //! Performs a scaling and translation transform on a list with each point being delayed by delay //! segments assigned based on a GPointIndexLookup. //! @param size Native size of the points within the command list. This is used for scaling. //! @param from Position and size to start from in local drawing coordinates. //! @param to Position and size to end at in local drawing coordinates. //! @param normalized Normalized animation position to transform to. //! @param interpolate InterpolateInt64Function to apply to each point individually //! @param lookup \ref GPointIndexLookup delay index that each point's delay is derived from. //! @param duration_fraction \ref animation_timing_segmented animation duration that each //! point would animate in within the animation's duration. //! @param is_offset true if the command list has already been offset another transform. When true, //! this prevents the transform from scaling the translation already present in the command list //! equivalent to `from.origin`. //! @see GPointIndexLookup void gdraw_command_list_scale_segmented_to( GDrawCommandList *list, GSize size, GRect from, GRect to, AnimationProgress normalized, InterpolateInt64Function interpolate, GPointIndexLookup *lookup, Fixed_S32_16 duration_fraction, bool is_offset); //! Performs a scaling and translation transform on an image with each point being delayed by delay //! segments assigned based on a GPointIndexLookup. //! @param from Position and size to start from in local drawing coordinates. //! @param to Position and size to end at from in local drawing coordinates. //! @param normalized Normalized animation position to transform to. //! @param interpolate InterpolateInt64Function to apply to each point individually //! @param lookup \ref GPointIndexLookup delay index that each point's delay is derived from. //! @param duration_fraction \ref animation_timing_segmented animation duration that each //! point would animate in within the animation's duration. //! @param is_offset true if the command list has already been offset another transform. When true, //! this prevents the transform from scaling the translation already present in the command list //! equivalent to `from.origin`. //! @see GPointIndexLookup void gdraw_command_image_scale_segmented_to( GDrawCommandImage *image, GRect from, GRect to, AnimationProgress normalized, InterpolateInt64Function interpolate, GPointIndexLookup *lookup, Fixed_S32_16 duration_fraction, bool is_offset); //! Scales and translates a GPoint. //! @param point Point to transform. //! @param size Dimensions of the canvas or image the point belongs to. //! @param from Position and size to start from in local drawing coordinates. //! @param to Position and size to end at from in local drawing coordinates. //! @param normalized Normalized animation position to transform to. //! @param interpolate InterpolateInt64Function to use for interpolation. GPoint gpoint_scale_to(GPoint point, GSize size, GRect from, GRect to, int32_t normalized, InterpolateInt64Function interpolate); //! Transforms the stroke width of a list as defined by a pair of GStrokeWidthOp. //! @param list GDrawCommandList to scale stroke width of //! @param from Fixed_S16_3 From stroke width operator value //! @param to Fixed_S16_3 To stroke width operator value //! @param from_op GStrokeWidthOp operation to start with //! @param to_op GStrokeWidthOp operation to end with //! @param progress AnimationProgress position of the transform //! @see GStrokeWidthOp void gdraw_command_list_scale_stroke_width(GDrawCommandList *list, Fixed_S16_3 from, Fixed_S16_3 to, GStrokeWidthOp from_op, GStrokeWidthOp to_op, AnimationProgress progress); //! Transforms the stroke width of an image as defined by a pair of GStrokeWidthOp. //! @param image GDrawCommandImage to scale stroke width of //! @param from Fixed_S16_3 From stroke width operator value //! @param to Fixed_S16_3 To stroke width operator value //! @param from_op GStrokeWidthOp operation to start with //! @param to_op GStrokeWidthOp operation to end with //! @param progress AnimationProgress position of the transform //! @see GStrokeWidthOp void gdraw_command_image_scale_stroke_width(GDrawCommandImage *image, Fixed_S16_3 from, Fixed_S16_3 to, GStrokeWidthOp from_op, GStrokeWidthOp to_op, AnimationProgress progress); void gdraw_command_frame_replace_color(GDrawCommandFrame *frame, GColor from, GColor to); void gdraw_command_replace_color(GDrawCommand *command, GColor from, GColor to);