Start redesign, WIP
* Implement callback animation type * Framebuffer items now have levels which specify the order of rendering * Framebuffer items now have parent rectangle which they can't draw outside of * Rectangles now support alpha blending
This commit is contained in:
		
							
								
								
									
										59
									
								
								animation.c
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								animation.c
									
									
									
									
									
								
							@@ -152,6 +152,12 @@ static void item_anim_on_finished(item_anim *anim)
 | 
			
		||||
        fb_remove_item(anim->item);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void call_anim_step(call_anim *anim, float interpolated)
 | 
			
		||||
{
 | 
			
		||||
    if(anim->callback)
 | 
			
		||||
        anim->callback(anim->data, interpolated);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void anim_update(uint32_t diff, void *data)
 | 
			
		||||
{
 | 
			
		||||
    struct anim_list *list = data;
 | 
			
		||||
@@ -201,6 +207,16 @@ static void anim_update(uint32_t diff, void *data)
 | 
			
		||||
            case ANIM_TYPE_ITEM:
 | 
			
		||||
                item_anim_step((item_anim*)anim, interpolated);
 | 
			
		||||
                break;
 | 
			
		||||
            case ANIM_TYPE_CALLBACK:
 | 
			
		||||
                call_anim_step((call_anim*)anim, interpolated);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(anim->on_step_call)
 | 
			
		||||
        {
 | 
			
		||||
            pthread_mutex_unlock(&list->mutex);
 | 
			
		||||
            anim->on_step_call(anim->on_step_data);
 | 
			
		||||
            pthread_mutex_lock(&list->mutex);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // remove complete animations
 | 
			
		||||
@@ -216,7 +232,9 @@ static void anim_update(uint32_t diff, void *data)
 | 
			
		||||
            switch(it->anim_type)
 | 
			
		||||
            {
 | 
			
		||||
                case ANIM_TYPE_ITEM:
 | 
			
		||||
                    pthread_mutex_unlock(&list->mutex);
 | 
			
		||||
                    item_anim_on_finished((item_anim*)anim);
 | 
			
		||||
                    pthread_mutex_lock(&list->mutex);
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -256,7 +274,7 @@ void anim_stop(void)
 | 
			
		||||
    pthread_mutex_unlock(&anim_list.mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void anim_fb_item_removed(void *item)
 | 
			
		||||
void anim_cancel_for(void *fb_item, int only_not_started)
 | 
			
		||||
{
 | 
			
		||||
    if(!anim_list.running)
 | 
			
		||||
        return;
 | 
			
		||||
@@ -265,12 +283,12 @@ void anim_fb_item_removed(void *item)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    struct anim_list_it *it, *to_remove;
 | 
			
		||||
    item_anim *anim;
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_lock(&anim_list.mutex);
 | 
			
		||||
    for(it = anim_list.first; it; )
 | 
			
		||||
    {
 | 
			
		||||
        if(it->anim_type == ANIM_TYPE_ITEM && ((item_anim*)it->anim)->item == item)
 | 
			
		||||
        if (it->anim_type == ANIM_TYPE_ITEM && ((item_anim*)it->anim)->item == fb_item &&
 | 
			
		||||
            (!only_not_started || it->anim->start_offset != 0))
 | 
			
		||||
        {
 | 
			
		||||
            to_remove = it;
 | 
			
		||||
            it = it->next;
 | 
			
		||||
@@ -347,3 +365,38 @@ void item_anim_add(item_anim *anim)
 | 
			
		||||
    it->anim = (anim_header*)anim;
 | 
			
		||||
    anim_list_append(it);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void item_anim_add_after(item_anim *anim)
 | 
			
		||||
{
 | 
			
		||||
    struct anim_list_it *it;
 | 
			
		||||
    pthread_mutex_lock(&anim_list.mutex);
 | 
			
		||||
    for(it = anim_list.first; it; it = it->next)
 | 
			
		||||
    {
 | 
			
		||||
        if(it->anim_type == ANIM_TYPE_ITEM && ((item_anim*)it->anim)->item == anim->item)
 | 
			
		||||
        {
 | 
			
		||||
            const int u = it->anim->start_offset + it->anim->duration - it->anim->elapsed;
 | 
			
		||||
            anim->start_offset = imax(anim->start_offset, u);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    pthread_mutex_unlock(&anim_list.mutex);
 | 
			
		||||
 | 
			
		||||
    item_anim_add(anim);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
call_anim *call_anim_create(void *data, call_anim_callback callback, int duration, int interpolator)
 | 
			
		||||
{
 | 
			
		||||
    call_anim *anim = mzalloc(sizeof(call_anim));
 | 
			
		||||
    anim->data = data;
 | 
			
		||||
    anim->callback = callback;
 | 
			
		||||
    anim->duration = duration;
 | 
			
		||||
    anim->interpolator = interpolator;
 | 
			
		||||
    return anim;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void call_anim_add(call_anim *anim)
 | 
			
		||||
{
 | 
			
		||||
    struct anim_list_it *it = mzalloc(sizeof(struct anim_list_it));
 | 
			
		||||
    it->anim_type = ANIM_TYPE_CALLBACK;
 | 
			
		||||
    it->anim = (anim_header*)anim;
 | 
			
		||||
    anim_list_append(it);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								animation.h
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								animation.h
									
									
									
									
									
								
							@@ -21,6 +21,7 @@
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
    ANIM_TYPE_ITEM,
 | 
			
		||||
    ANIM_TYPE_CALLBACK,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
@@ -39,7 +40,9 @@ typedef void (*animation_callback)(void*); // data
 | 
			
		||||
    uint32_t elapsed; \
 | 
			
		||||
    int interpolator; \
 | 
			
		||||
    void *on_finished_data; \
 | 
			
		||||
    animation_callback on_finished_call;
 | 
			
		||||
    animation_callback on_finished_call; \
 | 
			
		||||
    void *on_step_data; \
 | 
			
		||||
    animation_callback on_step_call;
 | 
			
		||||
 | 
			
		||||
typedef struct 
 | 
			
		||||
{
 | 
			
		||||
@@ -60,13 +63,27 @@ typedef struct
 | 
			
		||||
    int targetW, targetH;
 | 
			
		||||
} item_anim;
 | 
			
		||||
 | 
			
		||||
typedef void (*call_anim_callback)(void*, float); // data, interpolated
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    ANIM_HEADER
 | 
			
		||||
 | 
			
		||||
    call_anim_callback callback;
 | 
			
		||||
    void *data;
 | 
			
		||||
} call_anim;
 | 
			
		||||
 | 
			
		||||
void anim_init(void);
 | 
			
		||||
void anim_stop(void);
 | 
			
		||||
void anim_fb_item_removed(void *item);
 | 
			
		||||
void anim_cancel_for(void *fb_item, int only_not_started);
 | 
			
		||||
void anim_push_context(void);
 | 
			
		||||
void anim_pop_context(void);
 | 
			
		||||
 | 
			
		||||
item_anim *item_anim_create(void *fb_item, int duration, int interpolator);
 | 
			
		||||
void item_anim_add(item_anim *anim);
 | 
			
		||||
void item_anim_add_after(item_anim *anim);
 | 
			
		||||
 | 
			
		||||
call_anim *call_anim_create(void *data, call_anim_callback callback, int duration, int interpolator);
 | 
			
		||||
void call_anim_add(call_anim *anim);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										375
									
								
								framebuffer.c
									
									
									
									
									
								
							
							
						
						
									
										375
									
								
								framebuffer.c
									
									
									
									
									
								
							@@ -44,6 +44,9 @@
 | 
			
		||||
#define fb_memset(dst, what, len) android_memset32(dst, what, len)
 | 
			
		||||
#else
 | 
			
		||||
#define fb_memset(dst, what, len) android_memset16(dst, what, len)
 | 
			
		||||
  #ifdef HAS_NEON_BLEND
 | 
			
		||||
extern void scanline_col32cb16blend_neon(uint16_t *dst, uint32_t *col, size_t ct);
 | 
			
		||||
  #endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -51,15 +54,25 @@ uint32_t fb_width = 0;
 | 
			
		||||
uint32_t fb_height = 0;
 | 
			
		||||
int fb_rotation = 0; // in degrees, clockwise
 | 
			
		||||
 | 
			
		||||
fb_item_pos DEFAULT_FB_PARENT = {
 | 
			
		||||
    .x = 0,
 | 
			
		||||
    .y = 0,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct framebuffer fb;
 | 
			
		||||
static int fb_frozen = 0;
 | 
			
		||||
static int fb_force_generic = 0;
 | 
			
		||||
static fb_items_t fb_items = { NULL, NULL, NULL };
 | 
			
		||||
static fb_items_t **inactive_ctx = NULL;
 | 
			
		||||
 | 
			
		||||
static fb_context_t fb_ctx = { 
 | 
			
		||||
    .first_item = NULL,
 | 
			
		||||
    .msgbox = NULL,
 | 
			
		||||
    .mutex = PTHREAD_MUTEX_INITIALIZER
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static fb_context_t **inactive_ctx = NULL;
 | 
			
		||||
static uint8_t **fb_rot_helpers = NULL;
 | 
			
		||||
static pthread_mutex_t fb_items_mutex = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
static pthread_mutex_t fb_update_mutex = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
static pthread_t fb_draw_thread;
 | 
			
		||||
static pthread_mutex_t fb_update_mutex = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
static volatile int fb_draw_requested = 0;
 | 
			
		||||
static volatile int fb_draw_run = 0;
 | 
			
		||||
static volatile int fb_draw_futex = 0;
 | 
			
		||||
@@ -179,6 +192,9 @@ int fb_open(int rotation)
 | 
			
		||||
    fb_dump_info();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    DEFAULT_FB_PARENT.w = fb_width;
 | 
			
		||||
    DEFAULT_FB_PARENT.h = fb_height;
 | 
			
		||||
 | 
			
		||||
    fb_update();
 | 
			
		||||
 | 
			
		||||
    fb_draw_run = 1;
 | 
			
		||||
@@ -344,9 +360,9 @@ int fb_clone(char **buff)
 | 
			
		||||
    int len = fb.size;
 | 
			
		||||
    *buff = malloc(len);
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_lock(&fb_items_mutex);
 | 
			
		||||
    pthread_mutex_lock(&fb_update_mutex);
 | 
			
		||||
    memcpy(*buff, fb.buffer, len);
 | 
			
		||||
    pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
    pthread_mutex_unlock(&fb_update_mutex);
 | 
			
		||||
 | 
			
		||||
    return len;
 | 
			
		||||
}
 | 
			
		||||
@@ -371,6 +387,75 @@ px_type fb_convert_color(uint32_t c)
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void fb_ctx_put_it_before(fb_item_header *new_it, fb_item_header *next_it)
 | 
			
		||||
{
 | 
			
		||||
    if(next_it->prev)
 | 
			
		||||
    {
 | 
			
		||||
        next_it->prev->next = new_it;
 | 
			
		||||
        new_it->prev = next_it->prev;
 | 
			
		||||
    }
 | 
			
		||||
    new_it->next = next_it;
 | 
			
		||||
    next_it->prev = new_it;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void fb_ctx_put_it_after(fb_item_header *new_it, fb_item_header *prev_it)
 | 
			
		||||
{
 | 
			
		||||
    if(prev_it->next)
 | 
			
		||||
    {
 | 
			
		||||
        prev_it->next->prev = new_it;
 | 
			
		||||
        new_it->next = prev_it->next;
 | 
			
		||||
    }
 | 
			
		||||
    new_it->prev = prev_it;
 | 
			
		||||
    prev_it->next = new_it;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fb_ctx_add_item(fb_context_t *ctx, void *item)
 | 
			
		||||
{
 | 
			
		||||
    fb_item_header *h = item;
 | 
			
		||||
    pthread_mutex_lock(&ctx->mutex);
 | 
			
		||||
 | 
			
		||||
    if(!ctx->first_item)
 | 
			
		||||
        ctx->first_item = item;
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        fb_item_header *itr = ctx->first_item;
 | 
			
		||||
        while(1)
 | 
			
		||||
        {
 | 
			
		||||
            if(itr->level > h->level)
 | 
			
		||||
            {
 | 
			
		||||
                fb_ctx_put_it_before(h, itr);
 | 
			
		||||
                itr = NULL;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(itr->next)
 | 
			
		||||
                itr = itr->next;
 | 
			
		||||
            else
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(itr)
 | 
			
		||||
            fb_ctx_put_it_after(h, itr);
 | 
			
		||||
    }
 | 
			
		||||
    pthread_mutex_unlock(&ctx->mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fb_ctx_rm_item(fb_context_t *ctx, void *item)
 | 
			
		||||
{
 | 
			
		||||
    fb_item_header *h = item;
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_lock(&ctx->mutex);
 | 
			
		||||
    if(!h->prev)
 | 
			
		||||
        ctx->first_item = h->next;
 | 
			
		||||
    else
 | 
			
		||||
        h->prev->next = h->next;
 | 
			
		||||
 | 
			
		||||
    if(h->next)
 | 
			
		||||
        h->next->prev = h->prev;
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_unlock(&ctx->mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fb_remove_item(void *item)
 | 
			
		||||
{
 | 
			
		||||
    switch(((fb_item_header*)item)->type)
 | 
			
		||||
@@ -390,7 +475,7 @@ void fb_remove_item(void *item)
 | 
			
		||||
 | 
			
		||||
void fb_destroy_item(void *item)
 | 
			
		||||
{
 | 
			
		||||
    anim_fb_item_removed(item);
 | 
			
		||||
    anim_cancel_for(item, 0);
 | 
			
		||||
 | 
			
		||||
    switch(((fb_item_header*)item)->type)
 | 
			
		||||
    {
 | 
			
		||||
@@ -425,30 +510,84 @@ void fb_destroy_item(void *item)
 | 
			
		||||
    free(item);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fb_draw_rect(fb_rect *r)
 | 
			
		||||
{
 | 
			
		||||
    px_type *bits = fb.buffer + (fb.stride*r->y) + r->x;
 | 
			
		||||
    px_type color = fb_convert_color(r->color);
 | 
			
		||||
    const int w = r->w*PIXEL_SIZE;
 | 
			
		||||
 | 
			
		||||
    int i;
 | 
			
		||||
    for(i = 0; i < r->h; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        fb_memset(bits, color, w);
 | 
			
		||||
        bits += fb.stride;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int blend_png(int value1, int value2, int alpha) {
 | 
			
		||||
    int r = (0xFF-alpha)*value1 + alpha*value2;
 | 
			
		||||
    return (r+1 + (r >> 8)) >> 8; // divide by 255
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fb_draw_rect(fb_rect *r)
 | 
			
		||||
{
 | 
			
		||||
    const uint8_t alpha = (r->color >> 24) & 0xFF;
 | 
			
		||||
    const px_type color = fb_convert_color(r->color);
 | 
			
		||||
 | 
			
		||||
    if(alpha == 0)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
#if PIXEL_SIZE == 2
 | 
			
		||||
    const uint8_t alpha5b = alpha >> 3;
 | 
			
		||||
    const uint8_t alpha6b = alpha >> 2;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    const int min_x = r->x >= r->parent->x ? 0 : r->parent->x - r->x;
 | 
			
		||||
    const int min_y = r->y >= r->parent->y ? 0 : r->parent->y - r->y;
 | 
			
		||||
    const int max_x = imin(r->w, r->parent->x + r->parent->w - r->x);
 | 
			
		||||
    const int max_y = imin(r->h, r->parent->y + r->parent->h - r->y);
 | 
			
		||||
    const int rendered_w = max_x - min_x;
 | 
			
		||||
 | 
			
		||||
    const int w = rendered_w*PIXEL_SIZE;
 | 
			
		||||
 | 
			
		||||
    px_type *bits = fb.buffer + (fb.stride*(r->y + min_y)) + r->x + min_x;
 | 
			
		||||
 | 
			
		||||
    int i, x;
 | 
			
		||||
    uint8_t *comps_bits;
 | 
			
		||||
    uint8_t *comps_clr = (uint8_t*)&color;
 | 
			
		||||
    for(i = min_y; i < max_y; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        if(alpha == 0xFF)
 | 
			
		||||
        {
 | 
			
		||||
            fb_memset(bits, color, w);
 | 
			
		||||
            bits += fb.stride;
 | 
			
		||||
        }
 | 
			
		||||
        // Do the blending
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
#ifdef MR_DISABLE_ALPHA
 | 
			
		||||
            fb_memset(bits, color, w);
 | 
			
		||||
            bits += fb.stride;
 | 
			
		||||
#else
 | 
			
		||||
  #if PIXEL_SIZE == 4
 | 
			
		||||
            for(x = 0; x < rendered_w; ++x)
 | 
			
		||||
            {
 | 
			
		||||
                comps_bits = (uint8_t*)bits;
 | 
			
		||||
                comps_bits[PX_IDX_R] = blend_png(comps_bits[PX_IDX_R], comps_clr[PX_IDX_R], alpha);
 | 
			
		||||
                comps_bits[PX_IDX_G] = blend_png(comps_bits[PX_IDX_G], comps_clr[PX_IDX_G], alpha);
 | 
			
		||||
                comps_bits[PX_IDX_B] = blend_png(comps_bits[PX_IDX_B], comps_clr[PX_IDX_B], alpha);
 | 
			
		||||
                comps_bits[PX_IDX_A] = 0xFF;
 | 
			
		||||
                ++bits;
 | 
			
		||||
            }
 | 
			
		||||
  #else
 | 
			
		||||
    #ifdef HAS_NEON_BLEND
 | 
			
		||||
                scanline_col32cb16blend_neon((uint16_t*)bits, &r->color, rendered_w);
 | 
			
		||||
                bits += rendered_w;
 | 
			
		||||
    #else
 | 
			
		||||
            for(x = 0; x < rendered_w; ++x)
 | 
			
		||||
            {
 | 
			
		||||
                *bits = (((31-alpha5b)*(*bits & 0x1F)            + (alpha5b*(*img & 0x1F))) / 31) |
 | 
			
		||||
                        ((((63-alpha6b)*((*bits & 0x7E0) >> 5)   + (alpha6b*((*img & 0x7E0) >> 5))) / 63) << 5) |
 | 
			
		||||
                        ((((31-alpha5b)*((*bits & 0xF800) >> 11) + (alpha5b*((*img & 0xF800) >> 11))) / 31) << 11);
 | 
			
		||||
                ++bits;
 | 
			
		||||
            }
 | 
			
		||||
    #endif
 | 
			
		||||
  #endif // PIXEL_SIZE
 | 
			
		||||
            bits += fb.stride - rendered_w;
 | 
			
		||||
#endif // MR_DISABLE_ALPHA
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fb_draw_img(fb_img *i)
 | 
			
		||||
{
 | 
			
		||||
    int y, x;
 | 
			
		||||
    px_type *bits = fb.buffer + (fb.stride*i->y) + i->x;
 | 
			
		||||
    px_type *img = i->data;
 | 
			
		||||
    const int w = i->w*PIXEL_SIZE;
 | 
			
		||||
    uint8_t alpha;
 | 
			
		||||
    uint8_t *comps_img, *comps_bits;
 | 
			
		||||
@@ -459,13 +598,14 @@ void fb_draw_img(fb_img *i)
 | 
			
		||||
    const uint8_t max_alpha = 31;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    const int min_x = i->x >= 0 ? 0 : i->x + i->w;
 | 
			
		||||
    const int min_y = i->y >= 0 ? 0 : i->y + i->h;
 | 
			
		||||
    const int max_x = imin(i->w, fb_width - i->x);
 | 
			
		||||
    const int max_y = imin(i->h, fb_height - i->y);
 | 
			
		||||
    const int min_x = i->x >= i->parent->x ? 0 : i->parent->x - i->x;
 | 
			
		||||
    const int min_y = i->y >= i->parent->y ? 0 : i->parent->y - i->y;
 | 
			
		||||
    const int max_x = imin(i->w, i->parent->x + i->parent->w - i->x);
 | 
			
		||||
    const int max_y = imin(i->h, i->parent->y + i->parent->h - i->y);
 | 
			
		||||
    const int rendered_w = max_x - min_x;
 | 
			
		||||
 | 
			
		||||
    img = (px_type*)(((uint32_t*)img) + min_y * i->w);
 | 
			
		||||
    px_type *bits = fb.buffer + (fb.stride*(i->y + min_y)) + i->x + min_x;
 | 
			
		||||
    px_type *img = (px_type*)(((uint32_t*)i->data) + (min_y * i->w) + min_x);
 | 
			
		||||
 | 
			
		||||
    for(y = min_y; y < max_y; ++y)
 | 
			
		||||
    {
 | 
			
		||||
@@ -517,42 +657,17 @@ void fb_draw_img(fb_img *i)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fb_generate_item_id()
 | 
			
		||||
int fb_generate_item_id(void)
 | 
			
		||||
{
 | 
			
		||||
    pthread_mutex_lock(&fb_items_mutex);
 | 
			
		||||
    pthread_mutex_lock(&fb_ctx.mutex);
 | 
			
		||||
    static int id = 0;
 | 
			
		||||
    int res = id++;
 | 
			
		||||
    pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
    pthread_mutex_unlock(&fb_ctx.mutex);
 | 
			
		||||
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fb_img *fb_add_text(int x, int y, uint32_t color, int size, const char *fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    fb_img *res;
 | 
			
		||||
    char txt[512];
 | 
			
		||||
    va_list ap;
 | 
			
		||||
    char *buff = txt;
 | 
			
		||||
 | 
			
		||||
    txt[0] = 0;
 | 
			
		||||
 | 
			
		||||
    va_start(ap, fmt);
 | 
			
		||||
    ret = vsnprintf(txt, sizeof(txt), fmt, ap);
 | 
			
		||||
    if(ret >= (int)sizeof(txt))
 | 
			
		||||
    {
 | 
			
		||||
        buff = malloc(ret+1);
 | 
			
		||||
        vsnprintf(buff, ret+1, fmt, ap);
 | 
			
		||||
    }
 | 
			
		||||
    va_end(ap);
 | 
			
		||||
 | 
			
		||||
    res = fb_add_text_long(x, y, color, size, buff);
 | 
			
		||||
    if(ret >= (int)sizeof(txt))
 | 
			
		||||
        free(buff);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fb_img *fb_add_text_justified(int x, int y, uint32_t color, int size, int justify, const char *fmt, ...)
 | 
			
		||||
fb_img *fb_add_text_lvl_justified(int level, int x, int y, uint32_t color, int size, int justify, const char *fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    fb_img *res;
 | 
			
		||||
@@ -571,29 +686,31 @@ fb_img *fb_add_text_justified(int x, int y, uint32_t color, int size, int justif
 | 
			
		||||
    }
 | 
			
		||||
    va_end(ap);
 | 
			
		||||
 | 
			
		||||
    res = fb_add_text_long_justified(x, y, color, size, justify, buff);
 | 
			
		||||
    res = fb_add_text_long_lvl_justified(level, x, y, color, size, justify, buff);
 | 
			
		||||
    if(ret >= (int)sizeof(txt))
 | 
			
		||||
        free(buff);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fb_img *fb_add_text_long_justified(int x, int y, uint32_t color, int size, int justify, const char *text)
 | 
			
		||||
fb_img *fb_add_text_long_lvl_justified(int level, int x, int y, uint32_t color, int size, int justify, const char *text)
 | 
			
		||||
{
 | 
			
		||||
    fb_img *img = fb_text_create_item(x, y, color, size, justify, text);
 | 
			
		||||
    if(img)
 | 
			
		||||
    {
 | 
			
		||||
        pthread_mutex_lock(&fb_items_mutex);
 | 
			
		||||
        list_add(img, &fb_items.imgs);
 | 
			
		||||
        pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
        img->level = level;
 | 
			
		||||
        fb_ctx_add_item(&fb_ctx, img);
 | 
			
		||||
    }
 | 
			
		||||
    return img;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fb_rect *fb_add_rect(int x, int y, int w, int h, uint32_t color)
 | 
			
		||||
fb_rect *fb_add_rect_lvl(int level, int x, int y, int w, int h, uint32_t color)
 | 
			
		||||
{
 | 
			
		||||
    fb_rect *r = malloc(sizeof(fb_rect));
 | 
			
		||||
    fb_rect *r = mzalloc(sizeof(fb_rect));
 | 
			
		||||
    r->id = fb_generate_item_id();
 | 
			
		||||
    r->type = FB_IT_RECT;
 | 
			
		||||
    r->parent = &DEFAULT_FB_PARENT;
 | 
			
		||||
    r->level = level;
 | 
			
		||||
 | 
			
		||||
    r->x = x;
 | 
			
		||||
    r->y = y;
 | 
			
		||||
 | 
			
		||||
@@ -601,10 +718,7 @@ fb_rect *fb_add_rect(int x, int y, int w, int h, uint32_t color)
 | 
			
		||||
    r->h = h;
 | 
			
		||||
    r->color = color;
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_lock(&fb_items_mutex);
 | 
			
		||||
    list_add(r, &fb_items.rects);
 | 
			
		||||
    pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
 | 
			
		||||
    fb_ctx_add_item(&fb_ctx, r);
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -631,7 +745,10 @@ void fb_add_rect_notfilled(int x, int y, int w, int h, uint32_t color, int thick
 | 
			
		||||
fb_img *fb_add_img(int x, int y, int w, int h, int img_type, px_type *data)
 | 
			
		||||
{
 | 
			
		||||
    fb_img *result = mzalloc(sizeof(fb_img));
 | 
			
		||||
    result->id = fb_generate_item_id();
 | 
			
		||||
    result->type = FB_IT_IMG;
 | 
			
		||||
    result->parent = &DEFAULT_FB_PARENT;
 | 
			
		||||
    result->level = LEVEL_PNG;
 | 
			
		||||
    result->x = x;
 | 
			
		||||
    result->y = y;
 | 
			
		||||
    result->img_type = img_type;
 | 
			
		||||
@@ -639,10 +756,7 @@ fb_img *fb_add_img(int x, int y, int w, int h, int img_type, px_type *data)
 | 
			
		||||
    result->w = w;
 | 
			
		||||
    result->h = h;
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_lock(&fb_items_mutex);
 | 
			
		||||
    list_add(result, &fb_items.imgs);
 | 
			
		||||
    pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
 | 
			
		||||
    fb_ctx_add_item(&fb_ctx, result);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -660,9 +774,8 @@ void fb_rm_rect(fb_rect *r)
 | 
			
		||||
    if(!r)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_lock(&fb_items_mutex);
 | 
			
		||||
    list_rm_noreorder(r, &fb_items.rects, &fb_destroy_item);
 | 
			
		||||
    pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
    fb_ctx_rm_item(&fb_ctx, r);
 | 
			
		||||
    fb_destroy_item(r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fb_rm_text(fb_img *i)
 | 
			
		||||
@@ -675,17 +788,16 @@ void fb_rm_img(fb_img *i)
 | 
			
		||||
    if(!i)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_lock(&fb_items_mutex);
 | 
			
		||||
    list_rm_noreorder(i, &fb_items.imgs, &fb_destroy_item);
 | 
			
		||||
    pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
    fb_ctx_rm_item(&fb_ctx, i);
 | 
			
		||||
    fb_destroy_item(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define BOX_BORDER (2*DPI_MUL)
 | 
			
		||||
#define SHADOW (10*DPI_MUL)
 | 
			
		||||
fb_msgbox *fb_create_msgbox(int w, int h, int bgcolor)
 | 
			
		||||
{
 | 
			
		||||
    if(fb_items.msgbox)
 | 
			
		||||
        return fb_items.msgbox;
 | 
			
		||||
    if(fb_ctx.msgbox)
 | 
			
		||||
        return fb_ctx.msgbox;
 | 
			
		||||
 | 
			
		||||
    fb_msgbox *box = mzalloc(sizeof(fb_msgbox));
 | 
			
		||||
 | 
			
		||||
@@ -704,9 +816,9 @@ fb_msgbox *fb_create_msgbox(int w, int h, int bgcolor)
 | 
			
		||||
    box->background[2] = fb_add_rect(x+BOX_BORDER, y+BOX_BORDER,
 | 
			
		||||
                                     w-BOX_BORDER*2, h-BOX_BORDER*2, bgcolor);
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_lock(&fb_items_mutex);
 | 
			
		||||
    fb_items.msgbox = box;
 | 
			
		||||
    pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
    pthread_mutex_lock(&fb_ctx.mutex);
 | 
			
		||||
    fb_ctx.msgbox = box;
 | 
			
		||||
    pthread_mutex_unlock(&fb_ctx.mutex);
 | 
			
		||||
    return box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -719,7 +831,7 @@ fb_img *fb_msgbox_add_text(int x, int y, int size, char *fmt, ...)
 | 
			
		||||
    vsnprintf(txt, sizeof(txt), fmt, ap);
 | 
			
		||||
    va_end(ap);
 | 
			
		||||
 | 
			
		||||
    fb_msgbox *box = fb_items.msgbox;
 | 
			
		||||
    fb_msgbox *box = fb_ctx.msgbox;
 | 
			
		||||
 | 
			
		||||
    fb_img *t = fb_text_create_item(x, y, WHITE, size, JUSTIFY_LEFT, txt);
 | 
			
		||||
 | 
			
		||||
@@ -732,9 +844,9 @@ fb_img *fb_msgbox_add_text(int x, int y, int size, char *fmt, ...)
 | 
			
		||||
    t->x += box->x;
 | 
			
		||||
    t->y += box->y;
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_lock(&fb_items_mutex);
 | 
			
		||||
    pthread_mutex_lock(&fb_ctx.mutex);
 | 
			
		||||
    list_add(t, &box->imgs);
 | 
			
		||||
    pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
    pthread_mutex_unlock(&fb_ctx.mutex);
 | 
			
		||||
    return t;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -743,24 +855,24 @@ void fb_msgbox_rm_text(fb_img *text)
 | 
			
		||||
    if(!text)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_lock(&fb_items_mutex);
 | 
			
		||||
    if(fb_items.msgbox)
 | 
			
		||||
        list_rm_noreorder(text, &fb_items.msgbox->imgs, &fb_destroy_item);
 | 
			
		||||
    pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
    pthread_mutex_lock(&fb_ctx.mutex);
 | 
			
		||||
    if(fb_ctx.msgbox)
 | 
			
		||||
        list_rm_noreorder(text, &fb_ctx.msgbox->imgs, &fb_destroy_item);
 | 
			
		||||
    pthread_mutex_unlock(&fb_ctx.mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fb_destroy_msgbox(void)
 | 
			
		||||
{
 | 
			
		||||
    pthread_mutex_lock(&fb_items_mutex);
 | 
			
		||||
    if(!fb_items.msgbox)
 | 
			
		||||
    pthread_mutex_lock(&fb_ctx.mutex);
 | 
			
		||||
    if(!fb_ctx.msgbox)
 | 
			
		||||
    {
 | 
			
		||||
        pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
        pthread_mutex_unlock(&fb_ctx.mutex);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fb_msgbox *box = fb_items.msgbox;
 | 
			
		||||
    fb_items.msgbox = NULL;
 | 
			
		||||
    pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
    fb_msgbox *box = fb_ctx.msgbox;
 | 
			
		||||
    fb_ctx.msgbox = NULL;
 | 
			
		||||
    pthread_mutex_unlock(&fb_ctx.mutex);
 | 
			
		||||
 | 
			
		||||
    list_clear(&box->imgs, &fb_destroy_item);
 | 
			
		||||
 | 
			
		||||
@@ -773,10 +885,15 @@ void fb_destroy_msgbox(void)
 | 
			
		||||
 | 
			
		||||
void fb_clear(void)
 | 
			
		||||
{
 | 
			
		||||
    pthread_mutex_lock(&fb_items_mutex);
 | 
			
		||||
    list_clear(&fb_items.rects, &fb_destroy_item);
 | 
			
		||||
    list_clear(&fb_items.imgs, &fb_destroy_item);
 | 
			
		||||
    pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
    pthread_mutex_lock(&fb_ctx.mutex);
 | 
			
		||||
    fb_item_header *it, *next;
 | 
			
		||||
    for(it = fb_ctx.first_item; it; it = next)
 | 
			
		||||
    {
 | 
			
		||||
        next = it->next;
 | 
			
		||||
        fb_destroy_item(it);
 | 
			
		||||
    }
 | 
			
		||||
    fb_ctx.first_item = NULL;
 | 
			
		||||
    pthread_mutex_unlock(&fb_ctx.mutex);
 | 
			
		||||
 | 
			
		||||
    fb_destroy_msgbox();
 | 
			
		||||
 | 
			
		||||
@@ -792,9 +909,7 @@ static inline int blend(int value1, int value2) {
 | 
			
		||||
    return (r+1 + (r >> 8)) >> 8; // divide by 255
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
#ifdef HAS_NEON_BLEND
 | 
			
		||||
extern void scanline_col32cb16blend_neon(uint16_t *dst, uint32_t *col, size_t ct);
 | 
			
		||||
#else
 | 
			
		||||
#ifndef HAS_NEON_BLEND
 | 
			
		||||
#define ALPHA5 0x04
 | 
			
		||||
#define ALPHA6 0x08
 | 
			
		||||
#define BLEND_CLR5 0x03
 | 
			
		||||
@@ -841,24 +956,31 @@ void fb_draw_overlay(void)
 | 
			
		||||
static void fb_draw(void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t i;
 | 
			
		||||
    pthread_mutex_lock(&fb_items_mutex);
 | 
			
		||||
    fb_item_header *it;
 | 
			
		||||
    pthread_mutex_lock(&fb_ctx.mutex);
 | 
			
		||||
 | 
			
		||||
    fb_fill(BLACK);
 | 
			
		||||
    fb_fill(0xFFE0E0E0);
 | 
			
		||||
 | 
			
		||||
    // rectangles
 | 
			
		||||
    for(i = 0; fb_items.rects && fb_items.rects[i]; ++i)
 | 
			
		||||
        fb_draw_rect(fb_items.rects[i]);
 | 
			
		||||
 | 
			
		||||
    // images
 | 
			
		||||
    for(i = 0; fb_items.imgs && fb_items.imgs[i]; ++i)
 | 
			
		||||
        fb_draw_img(fb_items.imgs[i]);
 | 
			
		||||
    for(it = fb_ctx.first_item; it; it = it->next)
 | 
			
		||||
    {
 | 
			
		||||
        switch(it->type)
 | 
			
		||||
        {
 | 
			
		||||
            case FB_IT_RECT:
 | 
			
		||||
                fb_draw_rect((fb_rect*)it);
 | 
			
		||||
                break;
 | 
			
		||||
            case FB_IT_IMG:
 | 
			
		||||
                fb_draw_img((fb_img*)it);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // msg box
 | 
			
		||||
    if(fb_items.msgbox)
 | 
			
		||||
    if(fb_ctx.msgbox)
 | 
			
		||||
    {
 | 
			
		||||
        fb_draw_overlay();
 | 
			
		||||
 | 
			
		||||
        fb_msgbox *box = fb_items.msgbox;
 | 
			
		||||
        fb_msgbox *box = fb_ctx.msgbox;
 | 
			
		||||
 | 
			
		||||
        for(i = 0; i < ARRAY_SIZE(box->background); ++i)
 | 
			
		||||
            fb_draw_rect(box->background[i]);
 | 
			
		||||
@@ -867,7 +989,7 @@ static void fb_draw(void)
 | 
			
		||||
            fb_draw_img(box->imgs[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
    pthread_mutex_unlock(&fb_ctx.mutex);
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_lock(&fb_update_mutex);
 | 
			
		||||
    fb_update();
 | 
			
		||||
@@ -884,16 +1006,16 @@ void fb_freeze(int freeze)
 | 
			
		||||
 | 
			
		||||
void fb_push_context(void)
 | 
			
		||||
{
 | 
			
		||||
    fb_items_t *ctx = mzalloc(sizeof(fb_items_t));
 | 
			
		||||
    fb_context_t *ctx = mzalloc(sizeof(fb_context_t));
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_lock(&fb_items_mutex);
 | 
			
		||||
    pthread_mutex_lock(&fb_ctx.mutex);
 | 
			
		||||
 | 
			
		||||
    list_move(&fb_items.rects, &ctx->rects);
 | 
			
		||||
    list_move(&fb_items.imgs, &ctx->imgs);
 | 
			
		||||
    ctx->msgbox = fb_items.msgbox;
 | 
			
		||||
    fb_items.msgbox = NULL;
 | 
			
		||||
    ctx->first_item = fb_ctx.first_item;
 | 
			
		||||
    ctx->msgbox = fb_ctx.msgbox;
 | 
			
		||||
    fb_ctx.first_item = NULL;
 | 
			
		||||
    fb_ctx.msgbox = NULL;
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
    pthread_mutex_unlock(&fb_ctx.mutex);
 | 
			
		||||
 | 
			
		||||
    list_add(ctx, &inactive_ctx);
 | 
			
		||||
}
 | 
			
		||||
@@ -906,15 +1028,14 @@ void fb_pop_context(void)
 | 
			
		||||
    fb_clear();
 | 
			
		||||
 | 
			
		||||
    int idx = list_item_count(inactive_ctx)-1;
 | 
			
		||||
    fb_items_t *ctx = inactive_ctx[idx];
 | 
			
		||||
    fb_context_t *ctx = inactive_ctx[idx];
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_lock(&fb_items_mutex);
 | 
			
		||||
    pthread_mutex_lock(&fb_ctx.mutex);
 | 
			
		||||
 | 
			
		||||
    list_move(&ctx->rects, &fb_items.rects);
 | 
			
		||||
    list_move(&ctx->imgs, &fb_items.imgs);
 | 
			
		||||
    fb_items.msgbox = ctx->msgbox;
 | 
			
		||||
    fb_ctx.first_item = ctx->first_item;
 | 
			
		||||
    fb_ctx.msgbox = ctx->msgbox;
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_unlock(&fb_items_mutex);
 | 
			
		||||
    pthread_mutex_unlock(&fb_ctx.mutex);
 | 
			
		||||
 | 
			
		||||
    list_rm_noreorder(ctx, &inactive_ctx, &free);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@
 | 
			
		||||
 | 
			
		||||
#include <linux/fb.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
#if defined(RECOVERY_BGRA) || defined(RECOVERY_RGBX)
 | 
			
		||||
#define PIXEL_SIZE 4
 | 
			
		||||
@@ -103,7 +104,7 @@ enum
 | 
			
		||||
    SIZE_SMALL     = 6,
 | 
			
		||||
    SIZE_NORMAL    = 10,
 | 
			
		||||
    SIZE_BIG       = 13,
 | 
			
		||||
    SIZE_EXTRA     = 18,
 | 
			
		||||
    SIZE_EXTRA     = 15,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern uint32_t fb_width;
 | 
			
		||||
@@ -140,16 +141,40 @@ enum
 | 
			
		||||
    JUSTIFY_RIGHT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define FB_ITEM_HEAD \
 | 
			
		||||
    int id; \
 | 
			
		||||
    int type; \
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
    LEVEL_RECT = 0,
 | 
			
		||||
    LEVEL_PNG  = 1,
 | 
			
		||||
    LEVEL_TEXT = 2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct fb_item_header;
 | 
			
		||||
 | 
			
		||||
#define FB_ITEM_POS \
 | 
			
		||||
    int x, y; \
 | 
			
		||||
    int w, h;
 | 
			
		||||
 | 
			
		||||
typedef struct 
 | 
			
		||||
{
 | 
			
		||||
    FB_ITEM_POS
 | 
			
		||||
} fb_item_pos;
 | 
			
		||||
 | 
			
		||||
extern fb_item_pos DEFAULT_FB_PARENT;
 | 
			
		||||
 | 
			
		||||
#define FB_ITEM_HEAD \
 | 
			
		||||
    FB_ITEM_POS \
 | 
			
		||||
    int id; \
 | 
			
		||||
    int type; \
 | 
			
		||||
    int level; \
 | 
			
		||||
    fb_item_pos *parent; \
 | 
			
		||||
    struct fb_item_header *prev; \
 | 
			
		||||
    struct fb_item_header *next;
 | 
			
		||||
 | 
			
		||||
struct fb_item_header
 | 
			
		||||
{
 | 
			
		||||
    FB_ITEM_HEAD
 | 
			
		||||
} fb_item_header;
 | 
			
		||||
};
 | 
			
		||||
typedef struct fb_item_header fb_item_header;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
@@ -193,25 +218,31 @@ typedef struct
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    fb_rect **rects;
 | 
			
		||||
    fb_img **imgs;
 | 
			
		||||
    fb_item_header *first_item;
 | 
			
		||||
    fb_msgbox *msgbox;
 | 
			
		||||
} fb_items_t;
 | 
			
		||||
    pthread_mutex_t mutex;
 | 
			
		||||
} fb_context_t;
 | 
			
		||||
 | 
			
		||||
void fb_remove_item(void *item);
 | 
			
		||||
int fb_generate_item_id();
 | 
			
		||||
int fb_generate_item_id(void);
 | 
			
		||||
 | 
			
		||||
fb_img *fb_add_text_lvl_justified(int level, int x, int y, uint32_t color, int size, int justify, const char *fmt, ...);
 | 
			
		||||
#define fb_add_text_justified(x, y, color, size, justify, fmt, args...) fb_add_text_lvl_justified(LEVEL_TEXT, x, y, color, size, justify, fmt, ##args)
 | 
			
		||||
#define fb_add_text(x, y, color, size, fmt, args...) fb_add_text_lvl_justified(LEVEL_TEXT, x, y, color, size, JUSTIFY_LEFT, fmt, ##args)
 | 
			
		||||
#define fb_add_text_lvl(level, x, y, color, size, fmt, args...) fb_add_text_lvl_justified(level, x, y, color, size, JUSTIFY_LEFT, fmt, ##args)
 | 
			
		||||
 | 
			
		||||
fb_img *fb_add_text_long_lvl_justified(int level, int x, int y, uint32_t color, int size, int justify, const char *text);
 | 
			
		||||
#define fb_add_text_long(x, y, color, size, text) fb_add_text_long_lvl_justified(LEVEL_TEXT, x, y, color, size, JUSTIFY_LEFT, text)
 | 
			
		||||
 | 
			
		||||
fb_img *fb_add_text(int x, int y, uint32_t color, int size, const char *fmt, ...);
 | 
			
		||||
fb_img *fb_add_text_justified(int x, int y, uint32_t color, int size, int justify, const char *fmt, ...);
 | 
			
		||||
fb_img *fb_add_text_long(int x, int y, uint32_t color, int size, const char *text);
 | 
			
		||||
fb_img *fb_add_text_long_justified(int x, int y, uint32_t color, int size, int justify, const char *text);
 | 
			
		||||
fb_img *fb_text_create_item(int x, int y, uint32_t color, int size, int justify, const char *txt);
 | 
			
		||||
void fb_text_set_content(fb_img *img, const char *text);
 | 
			
		||||
void fb_text_set_color(fb_img *img, uint32_t color);
 | 
			
		||||
void fb_text_drop_cache_unused(void);
 | 
			
		||||
void fb_text_destroy(fb_img *i);
 | 
			
		||||
 | 
			
		||||
fb_rect *fb_add_rect(int x, int y, int w, int h, uint32_t color);
 | 
			
		||||
fb_rect *fb_add_rect_lvl(int level, int x, int y, int w, int h, uint32_t color);
 | 
			
		||||
#define fb_add_rect(x, y, w, h, color) fb_add_rect_lvl(LEVEL_RECT, x, y, w, h, color)
 | 
			
		||||
 | 
			
		||||
fb_img *fb_add_img(int x, int y, int w, int h, int img_type, px_type *data);
 | 
			
		||||
fb_img *fb_add_png_img(int x, int y, int w, int h, const char *path);
 | 
			
		||||
void fb_add_rect_notfilled(int x, int y, int w, int h, uint32_t color, int thickness, fb_rect ***list);
 | 
			
		||||
@@ -237,6 +268,9 @@ int fb_clone(char **buff);
 | 
			
		||||
void fb_push_context(void);
 | 
			
		||||
void fb_pop_context(void);
 | 
			
		||||
 | 
			
		||||
void fb_ctx_add_item(fb_context_t *ctx, void *item);
 | 
			
		||||
void fb_ctx_rm_item(fb_context_t *ctx, void *item);
 | 
			
		||||
 | 
			
		||||
px_type *fb_png_get(const char *path, int w, int h);
 | 
			
		||||
void fb_png_release(px_type *data);
 | 
			
		||||
void fb_png_drop_unused(void);
 | 
			
		||||
 
 | 
			
		||||
@@ -281,11 +281,6 @@ static void destroy_line(struct text_line *line)
 | 
			
		||||
    free(line);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fb_img *fb_add_text_long(int x, int y, uint32_t color, int size, const char *text)
 | 
			
		||||
{
 | 
			
		||||
    return fb_add_text_long_justified(x, y, color, size, JUSTIFY_LEFT, text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct 
 | 
			
		||||
{
 | 
			
		||||
    char *text;
 | 
			
		||||
@@ -298,7 +293,10 @@ typedef struct
 | 
			
		||||
fb_img *fb_text_create_item(int x, int y, uint32_t color, int size, int justify, const char *text)
 | 
			
		||||
{
 | 
			
		||||
    fb_img *result = mzalloc(sizeof(fb_img));
 | 
			
		||||
    result->id = fb_generate_item_id();
 | 
			
		||||
    result->parent = &DEFAULT_FB_PARENT;
 | 
			
		||||
    result->type = FB_IT_IMG;
 | 
			
		||||
    result->level = LEVEL_TEXT;
 | 
			
		||||
    result->x = x;
 | 
			
		||||
    result->y = y;
 | 
			
		||||
    result->img_type = FB_IMG_TYPE_TEXT;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										243
									
								
								listview.c
									
									
									
									
									
								
							
							
						
						
									
										243
									
								
								listview.c
									
									
									
									
									
								
							@@ -25,10 +25,11 @@
 | 
			
		||||
#include "multirom_ui.h"
 | 
			
		||||
#include "workers.h"
 | 
			
		||||
#include "input.h"
 | 
			
		||||
#include "animation.h"
 | 
			
		||||
 | 
			
		||||
#define MARK_W (10*DPI_MUL)
 | 
			
		||||
#define MARK_H (50*DPI_MUL)
 | 
			
		||||
#define PADDING (20*DPI_MUL)
 | 
			
		||||
#define PADDING (25*DPI_MUL)
 | 
			
		||||
#define LINE_W (2*DPI_MUL)
 | 
			
		||||
#define SCROLL_DIST (20*DPI_MUL)
 | 
			
		||||
#define OVERSCROLL_H (130*DPI_MUL)
 | 
			
		||||
@@ -68,7 +69,8 @@ void listview_init_ui(listview *view)
 | 
			
		||||
{
 | 
			
		||||
    int x = view->x + view->w - PADDING/2 - LINE_W/2;
 | 
			
		||||
 | 
			
		||||
    fb_rect *scroll_line = fb_add_rect(x, view->y, LINE_W, view->h, GRAYISH);
 | 
			
		||||
    fb_rect *scroll_line = fb_add_rect(x, view->y, LINE_W, view->h, GRAY);
 | 
			
		||||
    scroll_line->parent = view;
 | 
			
		||||
    list_add(scroll_line, &view->ui_items);
 | 
			
		||||
 | 
			
		||||
    view->keyact_item_selected = -1;
 | 
			
		||||
@@ -76,6 +78,12 @@ void listview_init_ui(listview *view)
 | 
			
		||||
    view->touch.id = -1;
 | 
			
		||||
    view->touch.last_y = -1;
 | 
			
		||||
 | 
			
		||||
    if(!view->bg_rect)
 | 
			
		||||
    {
 | 
			
		||||
        view->bg_rect = fb_add_rect(view->x, view->y, view->w - PADDING, view->h, 0xFFE0E0E0);
 | 
			
		||||
        view->bg_rect->parent = view;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    add_touch_handler(&listview_touch_handler, view);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -91,6 +99,7 @@ void listview_destroy(listview *view)
 | 
			
		||||
    fb_rm_rect(view->scroll_mark);
 | 
			
		||||
    fb_rm_rect(view->overscroll_marks[0]);
 | 
			
		||||
    fb_rm_rect(view->overscroll_marks[1]);
 | 
			
		||||
    fb_rm_rect(view->bg_rect);
 | 
			
		||||
 | 
			
		||||
    free(view);
 | 
			
		||||
}
 | 
			
		||||
@@ -101,6 +110,7 @@ listview_item *listview_add_item(listview *view, int id, void *data)
 | 
			
		||||
    it->id = id;
 | 
			
		||||
    it->data = data;
 | 
			
		||||
    it->flags = 0;
 | 
			
		||||
    it->parent_rect = view;
 | 
			
		||||
 | 
			
		||||
    if(!view->items)
 | 
			
		||||
        keyaction_add(view->x, view->y, listview_keyaction_call, view);
 | 
			
		||||
@@ -126,9 +136,9 @@ void listview_update_ui(listview *view)
 | 
			
		||||
    for(i = 0; view->items && view->items[i]; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        it = view->items[i];
 | 
			
		||||
        it_h = (*view->item_height)(it->data);
 | 
			
		||||
        it_h = (*view->item_height)(it);
 | 
			
		||||
 | 
			
		||||
        visible = (int)(view->pos <= y && y+it_h-view->pos <= view->h);
 | 
			
		||||
        visible = (int)(view->pos <= y+it_h && y-view->pos <= view->h);
 | 
			
		||||
 | 
			
		||||
        if(!visible && (it->flags & IT_VISIBLE))
 | 
			
		||||
            (*view->item_hide)(it->data);
 | 
			
		||||
@@ -160,11 +170,14 @@ void listview_enable_scroll(listview *view, int enable)
 | 
			
		||||
    if(enable)
 | 
			
		||||
    {
 | 
			
		||||
        int x = view->x + view->w - PADDING/2 - MARK_W/2;
 | 
			
		||||
        view->scroll_mark = fb_add_rect(x, view->y, MARK_W, MARK_H, GRAYISH);
 | 
			
		||||
        view->scroll_mark = fb_add_rect(x, view->y, MARK_W, MARK_H, GRAY);
 | 
			
		||||
        view->scroll_mark->parent = view;
 | 
			
		||||
 | 
			
		||||
        view->overscroll_marks[0] = fb_add_rect(view->x, view->y, 0, OVERSCROLL_MARK_H, CLR_SECONDARY);
 | 
			
		||||
        view->overscroll_marks[0]->parent = view;
 | 
			
		||||
        view->overscroll_marks[1] = fb_add_rect(view->x, view->y+view->h-OVERSCROLL_MARK_H,
 | 
			
		||||
                                                0, OVERSCROLL_MARK_H, CLR_SECONDARY);
 | 
			
		||||
        view->overscroll_marks[1]->parent = view;
 | 
			
		||||
        workers_add(listview_bounceback, view);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
@@ -223,6 +236,8 @@ int listview_touch_handler(touch_event *ev, void *data)
 | 
			
		||||
        if(view->touch.hover)
 | 
			
		||||
        {
 | 
			
		||||
            view->touch.hover->flags |= IT_HOVER;
 | 
			
		||||
            view->touch.hover->touchX = ev->x;
 | 
			
		||||
            view->touch.hover->touchY = ev->y;
 | 
			
		||||
            listview_update_ui(view);
 | 
			
		||||
        }
 | 
			
		||||
        listview_keyaction_call(view, KEYACT_CLEAR);
 | 
			
		||||
@@ -280,6 +295,8 @@ void listview_select_item(listview *view, listview_item *it)
 | 
			
		||||
        view->selected->flags &= ~(IT_SELECTED);
 | 
			
		||||
    it->flags |= IT_SELECTED;
 | 
			
		||||
 | 
			
		||||
    view->bg_rect->color = 0xFFE0E0E0;
 | 
			
		||||
 | 
			
		||||
    view->selected = it;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -324,10 +341,10 @@ int listview_ensure_visible(listview *view, listview_item *it)
 | 
			
		||||
    {
 | 
			
		||||
        if(it == view->items[i])
 | 
			
		||||
            break;
 | 
			
		||||
        y += view->item_height(view->items[i]->data);
 | 
			
		||||
        y += view->item_height(view->items[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int last_h = view->items[i] ? view->item_height(view->items[i]->data) : 0;
 | 
			
		||||
    int last_h = view->items[i] ? view->item_height(view->items[i]) : 0;
 | 
			
		||||
 | 
			
		||||
    if((y + last_h) - view->pos > view->h)
 | 
			
		||||
        view->pos = (y + last_h) - view->h;
 | 
			
		||||
@@ -355,7 +372,7 @@ listview_item *listview_item_at(listview *view, int y_pos)
 | 
			
		||||
    for(i = 0; view->items && view->items[i]; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        it = view->items[i];
 | 
			
		||||
        it_h = (*view->item_height)(it->data);
 | 
			
		||||
        it_h = (*view->item_height)(it);
 | 
			
		||||
 | 
			
		||||
        if(y < y_pos && y+it_h > y_pos)
 | 
			
		||||
            return it;
 | 
			
		||||
@@ -427,9 +444,9 @@ void listview_update_keyact_frame(listview *view)
 | 
			
		||||
    int i;
 | 
			
		||||
    int y = view->y;
 | 
			
		||||
    for(i = 0; i < view->keyact_item_selected && view->items[i]; ++i)
 | 
			
		||||
        y += view->item_height(view->items[i]->data);
 | 
			
		||||
        y += view->item_height(view->items[i]);
 | 
			
		||||
 | 
			
		||||
    int h = view->item_height(view->items[i]->data);
 | 
			
		||||
    int h = view->item_height(view->items[i]);
 | 
			
		||||
    y -= view->pos;
 | 
			
		||||
 | 
			
		||||
    // top
 | 
			
		||||
@@ -447,11 +464,13 @@ void listview_update_keyact_frame(listview *view)
 | 
			
		||||
    listview_update_ui(view);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define ROM_ITEM_H (100*DPI_MUL)
 | 
			
		||||
#define ROM_ITEM_H (110*DPI_MUL)
 | 
			
		||||
#define ROM_ITEM_GROW (40*DPI_MUL)
 | 
			
		||||
#define ROM_BOX_PADDING (5*DPI_MUL)
 | 
			
		||||
#define ROM_ITEM_SEL_W (8*DPI_MUL)
 | 
			
		||||
#define ROM_ICON_PADDING (12*DPI_MUL)
 | 
			
		||||
#define ROM_ICON_PADDING (20*DPI_MUL)
 | 
			
		||||
#define ROM_ICON_H (ROM_ITEM_H-(ROM_ICON_PADDING*2))
 | 
			
		||||
#define ROM_TEXT_PADDING (100*DPI_MUL)
 | 
			
		||||
#define ROM_TEXT_PADDING (130*DPI_MUL)
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    char *text;
 | 
			
		||||
@@ -459,10 +478,14 @@ typedef struct
 | 
			
		||||
    char *icon_path;
 | 
			
		||||
    fb_text *text_it;
 | 
			
		||||
    fb_text *part_it;
 | 
			
		||||
    fb_rect *bottom_line;
 | 
			
		||||
    fb_rect *hover_rect;
 | 
			
		||||
    fb_rect *sel_rect;
 | 
			
		||||
    fb_rect *sel_rect_sh;
 | 
			
		||||
    fb_text *click_text;
 | 
			
		||||
    fb_rect *click_text_rect;
 | 
			
		||||
    fb_img *icon;
 | 
			
		||||
    int hover_removed;
 | 
			
		||||
    int it_sel_size;
 | 
			
		||||
} rom_item_data;
 | 
			
		||||
 | 
			
		||||
void *rom_item_create(const char *text, const char *partition, const char *icon)
 | 
			
		||||
@@ -471,6 +494,7 @@ void *rom_item_create(const char *text, const char *partition, const char *icon)
 | 
			
		||||
    memset(data, 0, sizeof(rom_item_data));
 | 
			
		||||
 | 
			
		||||
    data->text = strdup(text);
 | 
			
		||||
    data->it_sel_size = ROM_ITEM_H;
 | 
			
		||||
    if(partition)
 | 
			
		||||
        data->partition = strdup(partition);
 | 
			
		||||
    if(icon)
 | 
			
		||||
@@ -478,52 +502,205 @@ void *rom_item_create(const char *text, const char *partition, const char *icon)
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void rom_item_null_rect(void *data)
 | 
			
		||||
{
 | 
			
		||||
    fb_rect **rect = data;
 | 
			
		||||
    *rect = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void rom_item_grow(void *it_v)
 | 
			
		||||
{
 | 
			
		||||
    listview_item *it = it_v;
 | 
			
		||||
    rom_item_data *d = (rom_item_data*)it->data;
 | 
			
		||||
    d->sel_rect_sh->x = d->sel_rect->x+5;
 | 
			
		||||
    d->sel_rect_sh->y = d->sel_rect->y+5;
 | 
			
		||||
    d->sel_rect_sh->w = d->sel_rect->w;
 | 
			
		||||
    d->sel_rect_sh->h = d->sel_rect->h;
 | 
			
		||||
    //d->it_sel_size = d->sel_rect->h;
 | 
			
		||||
    //listview_update_ui((listview*)it->parent_rect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void rom_item_shrink(void *it_v, float interpolated)
 | 
			
		||||
{
 | 
			
		||||
    listview_item *it = it_v;
 | 
			
		||||
    rom_item_data *d = (rom_item_data*)it->data;
 | 
			
		||||
    if(d->sel_rect_sh)
 | 
			
		||||
    {
 | 
			
		||||
        d->sel_rect_sh->h = d->sel_rect->h;
 | 
			
		||||
        d->sel_rect_sh->y = d->sel_rect->y+5;
 | 
			
		||||
    }
 | 
			
		||||
    d->it_sel_size = (ROM_ITEM_H + ROM_ITEM_GROW) - ROM_ITEM_GROW*interpolated;
 | 
			
		||||
    listview_update_ui((listview*)it->parent_rect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void rom_item_shrink_finished(void *it_v)
 | 
			
		||||
{
 | 
			
		||||
    listview_item *it = it_v;
 | 
			
		||||
    rom_item_data *d = (rom_item_data*)it->data;
 | 
			
		||||
 | 
			
		||||
    fb_rm_rect(d->sel_rect);
 | 
			
		||||
    fb_rm_rect(d->sel_rect_sh);
 | 
			
		||||
    fb_rm_text(d->click_text);
 | 
			
		||||
    fb_rm_rect(d->click_text_rect);
 | 
			
		||||
    d->sel_rect = NULL;
 | 
			
		||||
    d->sel_rect_sh = NULL;
 | 
			
		||||
    d->click_text = NULL;
 | 
			
		||||
    d->click_text_rect = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void rom_item_alpha(void *it_v, float interpolated)
 | 
			
		||||
{
 | 
			
		||||
    listview_item *it = it_v;
 | 
			
		||||
    rom_item_data *d = (rom_item_data*)it->data;
 | 
			
		||||
 | 
			
		||||
    uint32_t alpha = 0xFF*interpolated;
 | 
			
		||||
    if(d->hover_removed)
 | 
			
		||||
        alpha = 0xFF - alpha;
 | 
			
		||||
    alpha <<= 24;
 | 
			
		||||
    d->sel_rect->color = (d->sel_rect->color & ~(0xFF << 24)) | alpha;
 | 
			
		||||
    d->sel_rect_sh->color = (d->sel_rect_sh->color & ~(0xFF << 24)) | alpha;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void rom_item_alpha_finished(void *it_v)
 | 
			
		||||
{
 | 
			
		||||
    listview_item *it = it_v;
 | 
			
		||||
    rom_item_data *d = (rom_item_data*)it->data;
 | 
			
		||||
 | 
			
		||||
    d->sel_rect_sh->color = (d->sel_rect_sh->color & ~(0xFF << 24)) | (0xFF << 24);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rom_item_draw(int x, int y, int w, listview_item *it)
 | 
			
		||||
{
 | 
			
		||||
    rom_item_data *d = (rom_item_data*)it->data;
 | 
			
		||||
    const int item_h = rom_item_height(it);
 | 
			
		||||
    if(!d->text_it)
 | 
			
		||||
    {
 | 
			
		||||
        d->text_it = fb_add_text(x+ROM_TEXT_PADDING, 0, WHITE, SIZE_BIG, d->text);
 | 
			
		||||
        d->bottom_line = fb_add_rect(x, 0, w, 1, 0xFF1B1B1B);
 | 
			
		||||
        d->text_it = fb_add_text(x+ROM_TEXT_PADDING, 0, BLACK, SIZE_BIG, d->text);
 | 
			
		||||
        d->text_it->parent = it->parent_rect;
 | 
			
		||||
 | 
			
		||||
        if(d->icon_path)
 | 
			
		||||
        {
 | 
			
		||||
            d->icon = fb_add_png_img(x+ROM_ICON_PADDING, 0, ROM_ICON_H, ROM_ICON_H, d->icon_path);
 | 
			
		||||
            d->icon->parent = it->parent_rect;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(d->partition)
 | 
			
		||||
        {
 | 
			
		||||
            d->part_it = fb_add_text(x+ROM_TEXT_PADDING, 0, GRAY, SIZE_SMALL, d->partition);
 | 
			
		||||
            d->part_it->parent = it->parent_rect;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    center_text(d->text_it, -1, y, -1, ROM_ITEM_H);
 | 
			
		||||
    d->bottom_line->y = y+ROM_ITEM_H-2;
 | 
			
		||||
    center_text(d->text_it, -1, y, -1, item_h);
 | 
			
		||||
 | 
			
		||||
    if(d->icon)
 | 
			
		||||
        d->icon->y = y + (ROM_ITEM_H/2 - ROM_ICON_H/2);
 | 
			
		||||
        d->icon->y = y + (item_h/2 - ROM_ICON_H/2);
 | 
			
		||||
 | 
			
		||||
    if(d->part_it)
 | 
			
		||||
        d->part_it->y = d->text_it->y + SIZE_BIG*16 + 2;
 | 
			
		||||
 | 
			
		||||
    if(it->flags & IT_HOVER)
 | 
			
		||||
   /* if(it->flags & IT_HOVER)
 | 
			
		||||
    {
 | 
			
		||||
        if(!d->hover_rect)
 | 
			
		||||
            d->hover_rect = fb_add_rect(x, 0, w, rom_item_height(it->data), CLR_SECONDARY);
 | 
			
		||||
        d->hover_rect->y = y;
 | 
			
		||||
        {
 | 
			
		||||
            d->hover_rect = fb_add_rect(it->touchX, it->touchY, 1, 1, 0xFFE0E0E0);
 | 
			
		||||
            INFO("touch %dx%d\n", it->touchX, it->touchY);
 | 
			
		||||
            d->hover_rect->parent = it->parent_rect;
 | 
			
		||||
 | 
			
		||||
            item_anim *anim = item_anim_create(d->hover_rect, 300, INTERPOLATOR_DECELERATE);
 | 
			
		||||
            anim->start_offset = 150;
 | 
			
		||||
            anim->targetX = x;
 | 
			
		||||
            anim->targetY = y;
 | 
			
		||||
            anim->targetW = w;
 | 
			
		||||
            anim->targetH = item_h;
 | 
			
		||||
            item_anim_add(anim);
 | 
			
		||||
            d->hover_removed = 0;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            d->hover_rect->y = y;
 | 
			
		||||
    }
 | 
			
		||||
    else if(d->hover_rect)
 | 
			
		||||
    {
 | 
			
		||||
        fb_rm_rect(d->hover_rect);
 | 
			
		||||
        d->hover_rect = NULL;
 | 
			
		||||
    }
 | 
			
		||||
        if(!d->hover_removed)
 | 
			
		||||
        {
 | 
			
		||||
            anim_cancel_for(d->hover_rect, 1);
 | 
			
		||||
 | 
			
		||||
            item_anim *anim = item_anim_create(d->hover_rect, 100, INTERPOLATOR_ACCELERATE);
 | 
			
		||||
            anim->targetX = it->touchX;
 | 
			
		||||
            anim->targetY = it->touchY;
 | 
			
		||||
            anim->targetW = 0;
 | 
			
		||||
            anim->targetH = 0;
 | 
			
		||||
            anim->destroy_item_when_finished = 1;
 | 
			
		||||
            anim->on_finished_data = &d->hover_rect;
 | 
			
		||||
            anim->on_finished_call = rom_item_null_rect;
 | 
			
		||||
            item_anim_add_after(anim);
 | 
			
		||||
            d->hover_removed = 1;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            d->hover_rect->y = y;
 | 
			
		||||
        }
 | 
			
		||||
    }*/
 | 
			
		||||
 | 
			
		||||
    if(it->flags & IT_SELECTED)
 | 
			
		||||
    {
 | 
			
		||||
        if(!d->sel_rect)
 | 
			
		||||
            d->sel_rect = fb_add_rect(x, 0, ROM_ITEM_SEL_W, ROM_ITEM_H, CLR_PRIMARY);
 | 
			
		||||
        d->sel_rect->y = y;
 | 
			
		||||
        {
 | 
			
		||||
            d->sel_rect_sh = fb_add_rect(x+7, y+7, w, item_h, GRAYISH & ~(0xFF << 24));
 | 
			
		||||
            d->sel_rect = fb_add_rect(x+7, y+7, w, item_h, WHITE & ~(0xFF << 24));
 | 
			
		||||
            d->sel_rect->parent = it->parent_rect;
 | 
			
		||||
 | 
			
		||||
            call_anim *canim = call_anim_create(it, rom_item_alpha, 300, INTERPOLATOR_DECELERATE);
 | 
			
		||||
            call_anim_add(canim);
 | 
			
		||||
 | 
			
		||||
            item_anim *anim = item_anim_create(d->sel_rect, 150, INTERPOLATOR_DECELERATE);
 | 
			
		||||
            anim->start_offset = 0;
 | 
			
		||||
            anim->targetX = d->sel_rect->x-7;
 | 
			
		||||
            anim->targetY = d->sel_rect->y-7;
 | 
			
		||||
            item_anim_add(anim);
 | 
			
		||||
 | 
			
		||||
            d->click_text = fb_add_text_lvl(11, 0, fb_height, BLACK, SIZE_EXTRA, "Tap again to boot this system");
 | 
			
		||||
            center_text(d->click_text, 0, -1, fb_width, -1);
 | 
			
		||||
            d->click_text->y += d->click_text->h;
 | 
			
		||||
 | 
			
		||||
            d->click_text_rect = fb_add_rect_lvl(10, 0, fb_height, fb_width-80, d->click_text->h+200, WHITE);
 | 
			
		||||
            d->click_text_rect->x = fb_width/2 - d->click_text_rect->w/2;
 | 
			
		||||
 | 
			
		||||
            anim = item_anim_create(d->click_text, 400, INTERPOLATOR_DECELERATE);
 | 
			
		||||
            anim->targetY = fb_height - d->click_text->h*1.5 - 40;
 | 
			
		||||
            item_anim_add(anim);
 | 
			
		||||
 | 
			
		||||
            anim = item_anim_create(d->click_text_rect, 400, INTERPOLATOR_DECELERATE);
 | 
			
		||||
            anim->targetY = fb_height - d->click_text->h*2.5 - 40;
 | 
			
		||||
            item_anim_add(anim);
 | 
			
		||||
 | 
			
		||||
            d->hover_removed = 0;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            /*d->sel_rect_sh->y = y+5;
 | 
			
		||||
            d->sel_rect->y = y;*/
 | 
			
		||||
        }
 | 
			
		||||
        //d->click_text->y = d->text_it->y + d->text_it->h + 15;
 | 
			
		||||
    }
 | 
			
		||||
    else if(d->sel_rect)
 | 
			
		||||
    else if(d->sel_rect && !d->hover_removed)
 | 
			
		||||
    {
 | 
			
		||||
        fb_rm_rect(d->sel_rect);
 | 
			
		||||
        d->sel_rect = NULL;
 | 
			
		||||
        d->hover_removed = 1;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        call_anim *canim = call_anim_create(it, rom_item_alpha, 200, INTERPOLATOR_ACCELERATE);
 | 
			
		||||
        canim->on_finished_data = it;
 | 
			
		||||
        canim->on_finished_call = rom_item_shrink_finished;
 | 
			
		||||
        call_anim_add(canim);
 | 
			
		||||
 | 
			
		||||
        item_anim *anim = item_anim_create(d->sel_rect, 200, INTERPOLATOR_ACCELERATE);
 | 
			
		||||
        anim->targetX = d->sel_rect->x+7;
 | 
			
		||||
        anim->targetY = d->sel_rect->y+7;
 | 
			
		||||
        item_anim_add(anim);
 | 
			
		||||
 | 
			
		||||
        anim = item_anim_create(d->click_text, 200, INTERPOLATOR_DECELERATE);
 | 
			
		||||
        anim->targetY = fb_height;
 | 
			
		||||
        item_anim_add(anim);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -535,20 +712,20 @@ void rom_item_hide(void *data)
 | 
			
		||||
 | 
			
		||||
    fb_rm_text(d->text_it);
 | 
			
		||||
    fb_rm_text(d->part_it);
 | 
			
		||||
    fb_rm_rect(d->bottom_line);
 | 
			
		||||
    fb_rm_rect(d->hover_rect);
 | 
			
		||||
    fb_rm_rect(d->sel_rect);
 | 
			
		||||
    fb_rm_rect(d->sel_rect_sh);
 | 
			
		||||
    fb_rm_img(d->icon);
 | 
			
		||||
 | 
			
		||||
    d->text_it = NULL;
 | 
			
		||||
    d->part_it = NULL;
 | 
			
		||||
    d->bottom_line = NULL;
 | 
			
		||||
    d->hover_rect = NULL;
 | 
			
		||||
    d->sel_rect = NULL;
 | 
			
		||||
    d->sel_rect_sh = NULL;
 | 
			
		||||
    d->icon = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int rom_item_height(void *data)
 | 
			
		||||
int rom_item_height(listview_item *it)
 | 
			
		||||
{
 | 
			
		||||
    return ROM_ITEM_H;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								listview.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								listview.h
									
									
									
									
									
								
							@@ -33,6 +33,8 @@ typedef struct
 | 
			
		||||
    int id;
 | 
			
		||||
    void *data;
 | 
			
		||||
    int flags;
 | 
			
		||||
    fb_item_header *parent_rect;
 | 
			
		||||
    int touchX, touchY;
 | 
			
		||||
} listview_item;
 | 
			
		||||
 | 
			
		||||
typedef struct 
 | 
			
		||||
@@ -47,8 +49,7 @@ typedef struct
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    int x, y;
 | 
			
		||||
    int w, h;
 | 
			
		||||
    FB_ITEM_POS
 | 
			
		||||
 | 
			
		||||
    int pos; // scroll pos
 | 
			
		||||
    int fullH; // height of all items
 | 
			
		||||
@@ -58,12 +59,13 @@ typedef struct
 | 
			
		||||
 | 
			
		||||
    void (*item_draw)(int, int, int, listview_item *); // x, y, w, item
 | 
			
		||||
    void (*item_hide)(void*); // data
 | 
			
		||||
    int (*item_height)(void*); // data
 | 
			
		||||
    int (*item_height)(listview_item *); // data, item
 | 
			
		||||
    void (*item_destroy)(listview_item *);
 | 
			
		||||
    void (*item_selected)(listview_item *, listview_item *); // prev, now
 | 
			
		||||
    void (*item_confirmed)(listview_item *); // item - confirmed by keyaction
 | 
			
		||||
 | 
			
		||||
    fb_item_header **ui_items;
 | 
			
		||||
    fb_rect *bg_rect;
 | 
			
		||||
    fb_rect *scroll_mark;
 | 
			
		||||
    fb_rect *overscroll_marks[2];
 | 
			
		||||
    fb_rect **keyact_frame;
 | 
			
		||||
@@ -94,7 +96,7 @@ int listview_keyaction_call(void *data, int act);
 | 
			
		||||
void *rom_item_create(const char *text, const char *partition, const char *icon);
 | 
			
		||||
void rom_item_draw(int x, int y, int w, listview_item *it);
 | 
			
		||||
void rom_item_hide(void *data);
 | 
			
		||||
int rom_item_height(void *data);
 | 
			
		||||
int rom_item_height(listview_item *it);
 | 
			
		||||
void rom_item_destroy(listview_item *it);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -258,7 +258,7 @@ void multirom_ui_setup_colors(int clr, uint32_t *primary, uint32_t *secondary)
 | 
			
		||||
{
 | 
			
		||||
    static const int clrs[][2] = {
 | 
			
		||||
        // Primary,   Secondary - OxAAGGBBRR
 | 
			
		||||
        { LBLUE,      LBLUE2 },     // CLRS_BLUE
 | 
			
		||||
        { 0xFF2F2FF7,     0xFF2F2FF7},     // CLRS_BLUE
 | 
			
		||||
        { 0xFFCC66AA, 0xFFCC89B6 }, // CLRS_PURPLE
 | 
			
		||||
        { 0xFF00BD8A, 0xFF51F2C9 }, // CLRS_GREEN
 | 
			
		||||
        { 0xFF008AFF, 0xFF51AEFF }, // CLRS_ORANGE
 | 
			
		||||
@@ -367,10 +367,10 @@ void multirom_ui_fill_rom_list(listview *view, int mask)
 | 
			
		||||
            select = it;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(select)
 | 
			
		||||
/*    if(select)
 | 
			
		||||
        listview_select_item(view, select);
 | 
			
		||||
    else if(view->items != NULL)
 | 
			
		||||
        listview_select_item(view, view->items[0]);
 | 
			
		||||
        listview_select_item(view, view->items[0]);*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int multirom_ui_touch_handler(touch_event *ev, void *data)
 | 
			
		||||
@@ -486,9 +486,6 @@ void *multirom_ui_tab_rom_init(int tab_type)
 | 
			
		||||
    t->list->item_selected = &multirom_ui_tab_rom_selected;
 | 
			
		||||
    t->list->item_confirmed = &multirom_ui_tab_rom_confirmed;
 | 
			
		||||
 | 
			
		||||
    t->boot_btn = mzalloc(sizeof(button));
 | 
			
		||||
    list_add(t->boot_btn, &t->buttons);
 | 
			
		||||
 | 
			
		||||
    cur_theme->tab_rom_init(themes_info->data, t, tab_type);
 | 
			
		||||
 | 
			
		||||
    listview_init_ui(t->list);
 | 
			
		||||
@@ -509,10 +506,6 @@ void *multirom_ui_tab_rom_init(int tab_type)
 | 
			
		||||
    int has_roms = (int)(t->list->items == NULL);
 | 
			
		||||
    multirom_ui_tab_rom_set_empty((void*)t, has_roms);
 | 
			
		||||
 | 
			
		||||
    t->boot_btn->clicked = &multirom_ui_tab_rom_boot_btn;
 | 
			
		||||
    button_init_ui(t->boot_btn, "Boot", SIZE_BIG);
 | 
			
		||||
    button_enable(t->boot_btn, !has_roms);
 | 
			
		||||
 | 
			
		||||
    if(tab_type == TAB_USB)
 | 
			
		||||
    {
 | 
			
		||||
        multirom_set_usb_refresh_handler(&multirom_ui_refresh_usb_handler);
 | 
			
		||||
@@ -535,8 +528,6 @@ void multirom_ui_tab_rom_destroy(void *data)
 | 
			
		||||
 | 
			
		||||
    listview_destroy(t->list);
 | 
			
		||||
 | 
			
		||||
    fb_rm_text(t->rom_name);
 | 
			
		||||
 | 
			
		||||
    if(t->usb_prog)
 | 
			
		||||
        progdots_destroy(t->usb_prog);
 | 
			
		||||
 | 
			
		||||
@@ -655,10 +646,6 @@ void multirom_ui_tab_rom_set_empty(void *data, int empty)
 | 
			
		||||
    tab_data_roms *t = (tab_data_roms*)data;
 | 
			
		||||
    int width = cur_theme->get_tab_width(themes_info->data);
 | 
			
		||||
 | 
			
		||||
    static const char *str[] = { "Select ROM to boot:", "No ROMs in this location!" };
 | 
			
		||||
    fb_text_set_content(t->title_text, str[empty]);
 | 
			
		||||
    center_text(t->title_text, t->list->x, -1, width, -1);
 | 
			
		||||
 | 
			
		||||
    if(t->boot_btn)
 | 
			
		||||
        button_enable(t->boot_btn, !empty);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -26,10 +26,12 @@
 | 
			
		||||
#include "../log.h"
 | 
			
		||||
#include "../animation.h"
 | 
			
		||||
 | 
			
		||||
#define HEADER_HEIGHT (75*DPI_MUL)
 | 
			
		||||
#define HEADER_HEIGHT (110*DPI_MUL)
 | 
			
		||||
#define STATUS_HEIGHT (33*DPI_MUL)
 | 
			
		||||
#define TABS_HEIGHT (HEADER_HEIGHT - STATUS_HEIGHT)
 | 
			
		||||
#define MIRI_W (90*DPI_MUL)
 | 
			
		||||
 | 
			
		||||
#define ROMS_FOOTER_H (130*DPI_MUL)
 | 
			
		||||
#define ROMS_HEADER_H (90*DPI_MUL)
 | 
			
		||||
#define ROMS_HEADER_H (20*DPI_MUL)
 | 
			
		||||
 | 
			
		||||
#define BOOTBTN_W (280*DPI_MUL)
 | 
			
		||||
#define BOOTBTN_H (80*DPI_MUL)
 | 
			
		||||
@@ -45,6 +47,10 @@
 | 
			
		||||
#define CLRBTN_TOTAL (CLRBTN_W+CLRBTN_B)
 | 
			
		||||
#define CLRBTN_Y (1150*DPI_MUL)
 | 
			
		||||
 | 
			
		||||
#define SELECTED_RECT_H (10*DPI_MUL)
 | 
			
		||||
 | 
			
		||||
#define COLOR_HIGHLIGHT 0xFF2F2FF7
 | 
			
		||||
 | 
			
		||||
static button *pong_btn = NULL;
 | 
			
		||||
static void destroy(multirom_theme_data *t)
 | 
			
		||||
{
 | 
			
		||||
@@ -64,26 +70,42 @@ static void init_header(multirom_theme_data *t)
 | 
			
		||||
 | 
			
		||||
    static const char *str[] = { "Internal", "USB", "Misc", "MultiROM" };
 | 
			
		||||
 | 
			
		||||
    fb_text *title = fb_add_text(0, 0, WHITE, SIZE_EXTRA, str[3]);
 | 
			
		||||
    center_text(title, 0, 0, x, HEADER_HEIGHT);
 | 
			
		||||
    // header background
 | 
			
		||||
    fb_add_rect(0, 0, fb_width, HEADER_HEIGHT, CLR_PRIMARY);
 | 
			
		||||
    //fb_add_rect(0, HEADER_HEIGHT, fb_width, (2*DPI_MUL), 0xFF7F07BC);
 | 
			
		||||
 | 
			
		||||
    //fb_text *title = fb_add_text(0, 0, WHITE, SIZE_NORMAL, str[3]);
 | 
			
		||||
    //center_text(title, 0, 0, x, STATUS_HEIGHT);
 | 
			
		||||
 | 
			
		||||
    int maxW = 0;
 | 
			
		||||
    for(i = 0; i < TAB_COUNT; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        tab_texts[i] = fb_add_text(0, 0, WHITE, SIZE_BIG, str[i]);
 | 
			
		||||
        maxW = imax(maxW, tab_texts[i]->w);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    maxW += (30*DPI_MUL);
 | 
			
		||||
    x = fb_width/2 - (maxW*TAB_COUNT)/2;
 | 
			
		||||
 | 
			
		||||
    fb_img *l = fb_add_png_img((20*DPI_MUL), HEADER_HEIGHT/2 - MIRI_W/2, MIRI_W, MIRI_W, "/realdata/media/multirom/miri.png");
 | 
			
		||||
 | 
			
		||||
    pong_btn = mzalloc(sizeof(button));
 | 
			
		||||
    pong_btn->w = x;
 | 
			
		||||
    pong_btn->h = HEADER_HEIGHT;
 | 
			
		||||
    pong_btn->x = l->x;
 | 
			
		||||
    pong_btn->y = l->y;
 | 
			
		||||
    pong_btn->w = l->w;
 | 
			
		||||
    pong_btn->h = l->h;
 | 
			
		||||
    pong_btn->clicked = &multirom_ui_start_pong;
 | 
			
		||||
    button_init_ui(pong_btn, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    for(i = 0; i < TAB_COUNT; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        tab_texts[i] = fb_add_text(0, 0, WHITE, SIZE_NORMAL, str[i]);
 | 
			
		||||
        center_text(tab_texts[i], x, 0, TAB_BTN_WIDTH, HEADER_HEIGHT);
 | 
			
		||||
 | 
			
		||||
        fb_add_rect(x, 0, 2, HEADER_HEIGHT, WHITE);
 | 
			
		||||
        center_text(tab_texts[i], x, 0, maxW, HEADER_HEIGHT);
 | 
			
		||||
 | 
			
		||||
        tab_btns[i] = malloc(sizeof(button));
 | 
			
		||||
        memset(tab_btns[i], 0, sizeof(button));
 | 
			
		||||
        tab_btns[i]->x = x;
 | 
			
		||||
        tab_btns[i]->w = TAB_BTN_WIDTH;
 | 
			
		||||
        tab_btns[i]->y = 0;
 | 
			
		||||
        tab_btns[i]->w = maxW;
 | 
			
		||||
        tab_btns[i]->h = HEADER_HEIGHT;
 | 
			
		||||
        tab_btns[i]->action = i;
 | 
			
		||||
        tab_btns[i]->clicked = &multirom_ui_switch;
 | 
			
		||||
@@ -91,65 +113,34 @@ static void init_header(multirom_theme_data *t)
 | 
			
		||||
 | 
			
		||||
        keyaction_add(tab_btns[i]->x, tab_btns[i]->y, button_keyaction_call, tab_btns[i]);
 | 
			
		||||
 | 
			
		||||
        x += TAB_BTN_WIDTH;
 | 
			
		||||
        x += maxW;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fb_add_rect(0, HEADER_HEIGHT, fb_width, 2, WHITE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void header_select(multirom_theme_data *t, int tab)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    for(i = 0; i < TAB_COUNT; ++i)
 | 
			
		||||
        fb_text_set_color(t->tab_texts[i], (i == tab) ? BLACK : WHITE);
 | 
			
		||||
 | 
			
		||||
    const int TAB_BTN_WIDTH = fb_width*0.21;
 | 
			
		||||
    const int TAB_BTN_WIDTH = t->tab_btns[0]->w;
 | 
			
		||||
 | 
			
		||||
    int dest_x = t->tab_btns[tab]->x;
 | 
			
		||||
    if(!t->selected_tab_rect)
 | 
			
		||||
        t->selected_tab_rect = fb_add_rect(0, 0, TAB_BTN_WIDTH, HEADER_HEIGHT, WHITE);
 | 
			
		||||
        t->selected_tab_rect = fb_add_rect(dest_x, HEADER_HEIGHT-SELECTED_RECT_H, TAB_BTN_WIDTH, SELECTED_RECT_H, WHITE);
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        anim_cancel_for(t->selected_tab_rect, 0);
 | 
			
		||||
 | 
			
		||||
    t->selected_tab_rect->x = fb_width - (TAB_BTN_WIDTH * (TAB_COUNT - tab));
 | 
			
		||||
        item_anim *anim = item_anim_create(t->selected_tab_rect, 150, INTERPOLATOR_DECELERATE);
 | 
			
		||||
        anim->targetX = dest_x;
 | 
			
		||||
        item_anim_add(anim);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tab_rom_init(multirom_theme_data *t, tab_data_roms *d, int tab_type)
 | 
			
		||||
{
 | 
			
		||||
    int base_y = fb_height-ROMS_FOOTER_H;
 | 
			
		||||
 | 
			
		||||
    d->rom_name = fb_add_text(0, 0, WHITE, SIZE_NORMAL, "");
 | 
			
		||||
 | 
			
		||||
    d->list->x = ROMS_HEADER_H;
 | 
			
		||||
    d->list->y = HEADER_HEIGHT+ROMS_HEADER_H;
 | 
			
		||||
    d->list->w = fb_width;
 | 
			
		||||
    d->list->h = fb_height - d->list->y - ROMS_FOOTER_H-20;
 | 
			
		||||
 | 
			
		||||
    // header
 | 
			
		||||
    d->title_text = fb_add_text(0, 0, CLR_PRIMARY, SIZE_BIG, "W");
 | 
			
		||||
    center_text(d->title_text, -1, HEADER_HEIGHT, -1, ROMS_HEADER_H);
 | 
			
		||||
    list_add(d->title_text, &d->ui_elements);
 | 
			
		||||
 | 
			
		||||
    // footer
 | 
			
		||||
    fb_rect *sep = fb_add_rect(0, fb_height-ROMS_FOOTER_H, fb_width, 2, CLR_PRIMARY);
 | 
			
		||||
    list_add(sep, &d->ui_elements);
 | 
			
		||||
 | 
			
		||||
    // boot btn
 | 
			
		||||
    d->boot_btn->x = fb_width - BOOTBTN_W - 20;
 | 
			
		||||
    d->boot_btn->y = base_y + (ROMS_FOOTER_H-BOOTBTN_H)/2;
 | 
			
		||||
    d->boot_btn->w = BOOTBTN_W;
 | 
			
		||||
    d->boot_btn->h = BOOTBTN_H;
 | 
			
		||||
 | 
			
		||||
    keyaction_add(d->boot_btn->x, d->boot_btn->y, button_keyaction_call, d->boot_btn);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void animation_finished(void *data)
 | 
			
		||||
{
 | 
			
		||||
    fb_img *t = fb_add_text(50, HEADER_HEIGHT, CLR_PRIMARY, SIZE_BIG, "Finished!");
 | 
			
		||||
    tab_data_misc *d = data;
 | 
			
		||||
    list_add(t, &d->ui_elements);
 | 
			
		||||
    fb_request_draw();
 | 
			
		||||
 | 
			
		||||
    item_anim *anim = item_anim_create(t, 3000, INTERPOLATOR_LINEAR);
 | 
			
		||||
    anim->targetY = fb_height - t->h - 20;
 | 
			
		||||
    anim->targetX = fb_width - t->w;
 | 
			
		||||
    item_anim_add(anim);
 | 
			
		||||
    d->list->w = fb_width - ROMS_HEADER_H*2;
 | 
			
		||||
    d->list->h = fb_height - d->list->y - ROMS_HEADER_H;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tab_misc_init(multirom_theme_data *t, tab_data_misc *d, int color_scheme)
 | 
			
		||||
@@ -157,34 +148,6 @@ static void tab_misc_init(multirom_theme_data *t, tab_data_misc *d, int color_sc
 | 
			
		||||
    int x = fb_width/2 - MISCBTN_W/2;
 | 
			
		||||
    int y = 270*DPI_MUL;
 | 
			
		||||
 | 
			
		||||
    fb_rect *rt = fb_add_rect(20*DPI_MUL, y, 0, 0, WHITE);
 | 
			
		||||
 | 
			
		||||
    list_add(rt, &d->ui_elements);
 | 
			
		||||
 | 
			
		||||
    item_anim *anim = item_anim_create(rt, 200, INTERPOLATOR_DECELERATE);
 | 
			
		||||
    anim->targetW = fb_width - 40*DPI_MUL;
 | 
			
		||||
    item_anim_add(anim);
 | 
			
		||||
 | 
			
		||||
    anim = item_anim_create(rt, 400, INTERPOLATOR_OVERSHOOT);
 | 
			
		||||
    anim->start_offset = 200;
 | 
			
		||||
    anim->targetH = fb_height - y - 200*DPI_MUL;
 | 
			
		||||
    item_anim_add(anim);
 | 
			
		||||
 | 
			
		||||
    anim = item_anim_create(rt, 200, INTERPOLATOR_ACCELERATE);
 | 
			
		||||
    anim->start_offset = 3000;
 | 
			
		||||
    anim->targetH = 10*DPI_MUL;
 | 
			
		||||
    item_anim_add(anim);
 | 
			
		||||
 | 
			
		||||
    anim = item_anim_create(rt, 500, INTERPOLATOR_ACCELERATE);
 | 
			
		||||
    anim->start_offset = 3200;
 | 
			
		||||
    anim->targetX = 20*DPI_MUL + (fb_width - 40*DPI_MUL);
 | 
			
		||||
    anim->targetW = 0;
 | 
			
		||||
    anim->on_finished_data = d;
 | 
			
		||||
    anim->on_finished_call = animation_finished;
 | 
			
		||||
    item_anim_add(anim);
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
    button *b = mzalloc(sizeof(button));
 | 
			
		||||
    b->x = x;
 | 
			
		||||
    b->y = y;
 | 
			
		||||
@@ -285,8 +248,7 @@ static int get_tab_height(multirom_theme_data *t)
 | 
			
		||||
 | 
			
		||||
static void set_rom_name(tab_data_roms *d, const char *name)
 | 
			
		||||
{
 | 
			
		||||
    fb_text_set_content(d->rom_name, name);
 | 
			
		||||
    center_text(d->rom_name, 0, fb_height-ROMS_FOOTER_H, fb_width-BOOTBTN_W-20, ROMS_FOOTER_H);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct multirom_theme theme_info_portrait = {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user