Subversion Repositories freemyipod

Rev

Rev 527 | Rev 695 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
527 theseven 1
//
2
//
3
//    Copyright 2011 TheSeven
4
//
5
//
6
//    This file is part of emCORE.
7
//
8
//    emCORE is free software: you can redistribute it and/or
9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
13
//    emCORE is distributed in the hope that it will be useful,
14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
24
#include "emcorelib.h"
25
#include "libui.h"
26
#include "chooser.h"
27
#include "chooser_renderer_iconflow.h"
28
 
29
 
30
static int chooser_renderer_iconflow_init(struct chooser_data* data)
31
{
32
    const struct chooser_renderer_iconflow_params* params;
33
    params = (const struct chooser_renderer_iconflow_params*)(data->info->rendererparams);
34
    if (params->version != CHOOSER_RENDERER_ICONFLOW_PARAMS_VERSION) return -1;
35
    data->rendererdata = malloc(sizeof(struct chooser_renderer_iconflow_data));
36
    if (!data->rendererdata) return -2;
37
    struct chooser_renderer_iconflow_data* rdata;
38
    rdata = (struct chooser_renderer_iconflow_data*)(data->rendererdata);
39
    rdata->viewposition = params->startposition * data->info->actionhandler->stepsperitem(data);
678 theseven 40
    rdata->accumulator = 0;
527 theseven 41
    rdata->lastupdate = USEC_TIMER;
42
    return 0;
43
}
44
 
45
static void chooser_renderer_iconflow_geticondata(int x, int y, int w, int h, int siv,
46
                                                  int dist, const struct libui_surface* icon,
47
                                                  int* ix, int* iy, int* io)
48
{
49
    *ix = x + (w - icon->size.x) * (dist + siv / 2) / siv;
50
    *iy = y + (h - icon->size.y) - (h - icon->size.y) * dist * dist * 2 / (siv * siv);
51
    *io = MAX(0, 255 - 510 * ABS(dist) / siv);
52
}
53
 
54
static enum chooser_result chooser_renderer_iconflow_render(struct chooser_data* data)
55
{
56
    enum chooser_result rc = CHOOSER_RESULT_OK;
57
    const struct chooser_renderer_iconflow_params* params;
58
    params = (const struct chooser_renderer_iconflow_params*)(data->info->rendererparams);
59
    struct chooser_renderer_iconflow_data* rdata;
60
    rdata = (struct chooser_renderer_iconflow_data*)(data->rendererdata);
61
    long time = USEC_TIMER;
62
    long timediff = time - rdata->lastupdate;
63
    int distance = data->position - rdata->viewposition;
64
    if (distance) rc = CHOOSER_RESULT_REDRAW;
65
    int factor = params->smoothness / timediff + 1;
66
    rdata->accumulator += distance;
67
    distance = rdata->accumulator / factor;
68
    rdata->accumulator -= distance * factor;
69
    rdata->viewposition += distance;
70
    rdata->lastupdate = time;
71
    if (params->copy_dest.buf.addr == params->fill_dest.loc.buf.addr
72
     && params->copy_dest.buf.stride == params->fill_dest.loc.buf.stride
73
     && params->copy_dest.pos.x == params->fill_dest.loc.pos.x
74
     && params->copy_dest.pos.y == params->fill_dest.loc.pos.y
75
     && params->copy_src.size.x == params->fill_dest.size.x
76
     && params->copy_src.size.y == params->fill_dest.size.y && params->copy_src.loc.buf.addr)
77
    {
78
        blendcolor(params->copy_src.size.x, params->copy_src.size.y, params->fill_color,
79
                   params->copy_dest.buf.addr, params->copy_dest.pos.x,
80
                   params->copy_dest.pos.y, params->copy_dest.buf.stride,
81
                   params->copy_src.loc.buf.addr, params->copy_src.loc.pos.x,
82
                   params->copy_src.loc.pos.y, params->copy_src.loc.buf.stride);
83
        if (params->bg_opacity && params->bg_dest.buf.addr && params->bg_src.loc.buf.addr)
84
            blenda(params->bg_src.size.x, params->bg_src.size.y, params->bg_opacity,
85
                   params->bg_dest.buf.addr, params->bg_dest.pos.x,
86
                   params->bg_dest.pos.y, params->bg_dest.buf.stride,
87
                   params->bg_dest.buf.addr, params->bg_dest.pos.x,
88
                   params->bg_dest.pos.y, params->bg_dest.buf.stride,
89
                   params->bg_src.loc.buf.addr, params->bg_src.loc.pos.x,
90
                   params->bg_src.loc.pos.y, params->bg_src.loc.buf.stride);
91
    }
92
    else if (params->copy_dest.buf.stride == params->bg_dest.buf.stride
93
     && params->bg_src.loc.buf.addr && params->copy_dest.buf.addr == params->bg_dest.buf.addr
94
     && params->copy_dest.pos.x == params->bg_dest.pos.x && !params->fill_dest.loc.buf.addr
95
     && params->copy_dest.pos.y == params->bg_dest.pos.y && params->copy_src.loc.buf.addr
96
     && params->copy_src.size.x == params->bg_src.size.x && params->copy_dest.buf.addr
97
     && params->copy_src.size.y == params->bg_src.size.y && params->bg_opacity)
98
    {
99
        blenda(params->copy_src.size.x, params->copy_src.size.y, params->bg_opacity,
100
               params->copy_dest.buf.addr, params->copy_dest.pos.x,
101
               params->copy_dest.pos.y, params->copy_dest.buf.stride,
102
               params->copy_src.loc.buf.addr, params->copy_src.loc.pos.x,
103
               params->copy_src.loc.pos.y, params->copy_src.loc.buf.stride,
104
               params->bg_src.loc.buf.addr, params->bg_src.loc.pos.x,
105
               params->bg_src.loc.pos.y, params->bg_src.loc.buf.stride);
106
    }
107
    else
108
    {
109
        if (params->copy_src.loc.buf.addr && params->copy_dest.buf.addr)
110
            blit(params->copy_src.size.x, params->copy_src.size.y, 3,
111
                 params->copy_dest.buf.addr, params->copy_dest.pos.x,
112
                 params->copy_dest.pos.y, params->copy_dest.buf.stride,
113
                 params->copy_src.loc.buf.addr, params->copy_src.loc.pos.x,
114
                 params->copy_src.loc.pos.y, params->copy_src.loc.buf.stride);
115
        if (params->fill_dest.loc.buf.addr)
116
            blendcolor(params->fill_dest.size.x, params->fill_dest.size.y, params->fill_color,
117
                       params->fill_dest.loc.buf.addr, params->fill_dest.loc.pos.x,
118
                       params->fill_dest.loc.pos.y, params->fill_dest.loc.buf.stride,
119
                       params->fill_dest.loc.buf.addr, params->fill_dest.loc.pos.x,
120
                       params->fill_dest.loc.pos.y, params->fill_dest.loc.buf.stride);
121
        if (params->bg_opacity && params->bg_src.loc.buf.addr && params->bg_dest.buf.addr)
122
            blenda(params->bg_src.size.x, params->bg_src.size.y, params->bg_opacity,
123
                   params->bg_dest.buf.addr, params->bg_dest.pos.x,
124
                   params->bg_dest.pos.y, params->bg_dest.buf.stride,
125
                   params->bg_dest.buf.addr, params->bg_dest.pos.x,
126
                   params->bg_dest.pos.y, params->bg_dest.buf.stride,
127
                   params->bg_src.loc.buf.addr, params->bg_src.loc.pos.x,
128
                   params->bg_src.loc.pos.y, params->bg_src.loc.buf.stride);
129
    }
130
    void* buf = params->viewport.loc.buf.addr;
131
    int stride = params->viewport.loc.buf.stride;
132
    int x = params->viewport.loc.pos.x;
133
    int y = params->viewport.loc.pos.y;
134
    int w = params->viewport.size.x;
135
    int h = params->viewport.size.y;
136
    int spi = data->info->actionhandler->stepsperitem(data);
137
    int dir = 1;
138
    int pos = spi / 2;
139
    int vpos = rdata->viewposition;
140
    int iiv = params->iconsinview;
141
    const struct chooser_renderer_iconflow_itemdata* iparams;
142
    const struct chooser_item* item = data->info->items;
143
    while (true)
144
    {
145
        if (item == data->selected && dir == 1)
146
        {
147
            dir = -1;
148
            item = &data->info->items[data->info->itemcount - 1];
149
            pos = spi * data->info->itemcount - spi / 2;
150
        }
151
        iparams = (const struct chooser_renderer_iconflow_itemdata*)(item->renderparams);
152
        const struct libui_surface* icon;
153
        if (item == data->selected) icon = &iparams->icon_selected;
154
        else icon = &iparams->icon;
155
        int ix, iy, io;
156
        int dist = pos - vpos;
157
        chooser_renderer_iconflow_geticondata(x, y, w, h, spi * iiv, dist, icon, &ix, &iy, &io);
158
        if (item == data->selected)
159
        {
160
            io = 255;
161
            if (iparams->text && iparams->text_color)
162
                rendertext(buf, params->text_pos.x - strlen(iparams->text) * get_font_width() / 2,
163
                           params->text_pos.y, stride, iparams->text_color, 0, iparams->text);
164
        }
165
        if (icon->loc.buf.addr && io && ix >= x && iy >= y
166
         && ix + icon->size.x <= x + w && iy + icon->size.y <= y + h)
167
            blenda(icon->size.x, icon->size.y, io, buf, ix, iy, stride, buf, ix, iy, stride,
168
                   icon->loc.buf.addr, icon->loc.pos.x, icon->loc.pos.y, icon->loc.buf.stride);
169
        if (item == data->selected) break;
170
        item += dir;
171
        pos += dir * spi;
172
    }
173
    if (params->preblit && params->preblit(data)) return rc;
174
    displaylcd(params->blit_dest.x, params->blit_dest.y, params->blit_src.size.x,
175
               params->blit_src.size.y, params->blit_src.loc.buf.addr, params->blit_src.loc.pos.x,
176
               params->blit_src.loc.pos.y, params->blit_src.loc.buf.stride);
177
    if (params->postblit) params->postblit(data);
178
    return rc;
179
}
180
 
181
static const struct chooser_item* chooser_renderer_iconflow_itematpixel(struct chooser_data* data,
182
                                                                        int x, int y)
183
{
184
    if (x < 0 || y < 0) return NULL;
185
    const struct chooser_renderer_iconflow_params* params;
186
    params = (const struct chooser_renderer_iconflow_params*)(data->info->rendererparams);
187
    if (x >= params->viewport.size.x || y >= params->viewport.size.y) return NULL;
188
    struct chooser_renderer_iconflow_data* rdata;
189
    rdata = (struct chooser_renderer_iconflow_data*)(data->rendererdata);
190
    const struct chooser_item* result = NULL;
191
    int vx = params->viewport.loc.pos.x;
192
    int vy = params->viewport.loc.pos.y;
193
    int vw = params->viewport.size.x;
194
    int vh = params->viewport.size.y;
195
    int spi = data->info->actionhandler->stepsperitem(data);
196
    int dir = 1;
197
    int pos = spi / 2;
198
    int vpos = rdata->viewposition;
199
    int iiv = params->iconsinview;
200
    const struct chooser_renderer_iconflow_itemdata* iparams;
201
    const struct chooser_item* item = data->info->items;
202
    while (true)
203
    {
204
        if (item == data->selected && dir == 1)
205
        {
206
            dir = -1;
207
            item = &data->info->items[data->info->itemcount - 1];
208
            pos = spi * data->info->itemcount - spi / 2;
209
        }
210
        iparams = (const struct chooser_renderer_iconflow_itemdata*)(item->renderparams);
211
        const struct libui_surface* icon;
212
        if (item == data->selected) icon = &iparams->icon_selected;
213
        else icon = &iparams->icon;
214
        int ix, iy, o;
215
        int dist = pos - vpos;
216
        chooser_renderer_iconflow_geticondata(vx, vy, vw, vh, spi * iiv, dist, icon, &ix, &iy, &o);
217
        if (x >= ix && y >= ix && x < ix + icon->size.x && y < iy + icon->size.y) result = item;
218
        if (item == data->selected) break;
219
        item += dir;
220
        pos += dir * spi;
221
    }
222
    return result;
223
}
224
 
225
static void chooser_renderer_iconflow_destroy(struct chooser_data* data)
226
{
227
    free(data->rendererdata);
228
}
229
 
230
 
231
const struct chooser_renderer chooser_renderer_iconflow = 
232
{
233
    .version = CHOOSER_RENDERER_VERSION,
234
    .init = chooser_renderer_iconflow_init,
235
    .render = chooser_renderer_iconflow_render,
236
    .itematpixel = chooser_renderer_iconflow_itematpixel,
237
    .destroy = chooser_renderer_iconflow_destroy
238
};