Subversion Repositories freemyipod

Rev

Rev 820 | 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);
695 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;
695 theseven 63
    if (!timediff) timediff = 1;
64
    int distance;
65
    if (!rdata->lastupdate) distance = 0;
66
    else distance = data->position - rdata->viewposition;
67
    int factor = params->smoothness / timediff;
68
    if (!factor) factor = 1;
527 theseven 69
    rdata->accumulator += distance;
70
    distance = rdata->accumulator / factor;
71
    rdata->accumulator -= distance * factor;
72
    rdata->viewposition += distance;
73
    rdata->lastupdate = time;
695 theseven 74
    if (data->position - rdata->viewposition) rc = CHOOSER_RESULT_REDRAW;
75
    else rdata->lastupdate = 0;
703 theseven 76
    const struct chooser_item* selected = data->selected;
527 theseven 77
    if (params->copy_dest.buf.addr == params->fill_dest.loc.buf.addr
78
     && params->copy_dest.buf.stride == params->fill_dest.loc.buf.stride
79
     && params->copy_dest.pos.x == params->fill_dest.loc.pos.x
80
     && params->copy_dest.pos.y == params->fill_dest.loc.pos.y
81
     && params->copy_src.size.x == params->fill_dest.size.x
82
     && params->copy_src.size.y == params->fill_dest.size.y && params->copy_src.loc.buf.addr)
83
    {
84
        blendcolor(params->copy_src.size.x, params->copy_src.size.y, params->fill_color,
85
                   params->copy_dest.buf.addr, params->copy_dest.pos.x,
86
                   params->copy_dest.pos.y, params->copy_dest.buf.stride,
87
                   params->copy_src.loc.buf.addr, params->copy_src.loc.pos.x,
88
                   params->copy_src.loc.pos.y, params->copy_src.loc.buf.stride);
89
        if (params->bg_opacity && params->bg_dest.buf.addr && params->bg_src.loc.buf.addr)
90
            blenda(params->bg_src.size.x, params->bg_src.size.y, params->bg_opacity,
91
                   params->bg_dest.buf.addr, params->bg_dest.pos.x,
92
                   params->bg_dest.pos.y, params->bg_dest.buf.stride,
93
                   params->bg_dest.buf.addr, params->bg_dest.pos.x,
94
                   params->bg_dest.pos.y, params->bg_dest.buf.stride,
95
                   params->bg_src.loc.buf.addr, params->bg_src.loc.pos.x,
96
                   params->bg_src.loc.pos.y, params->bg_src.loc.buf.stride);
97
    }
98
    else if (params->copy_dest.buf.stride == params->bg_dest.buf.stride
99
     && params->bg_src.loc.buf.addr && params->copy_dest.buf.addr == params->bg_dest.buf.addr
100
     && params->copy_dest.pos.x == params->bg_dest.pos.x && !params->fill_dest.loc.buf.addr
101
     && params->copy_dest.pos.y == params->bg_dest.pos.y && params->copy_src.loc.buf.addr
102
     && params->copy_src.size.x == params->bg_src.size.x && params->copy_dest.buf.addr
103
     && params->copy_src.size.y == params->bg_src.size.y && params->bg_opacity)
104
    {
105
        blenda(params->copy_src.size.x, params->copy_src.size.y, params->bg_opacity,
106
               params->copy_dest.buf.addr, params->copy_dest.pos.x,
107
               params->copy_dest.pos.y, params->copy_dest.buf.stride,
108
               params->copy_src.loc.buf.addr, params->copy_src.loc.pos.x,
109
               params->copy_src.loc.pos.y, params->copy_src.loc.buf.stride,
110
               params->bg_src.loc.buf.addr, params->bg_src.loc.pos.x,
111
               params->bg_src.loc.pos.y, params->bg_src.loc.buf.stride);
112
    }
113
    else
114
    {
115
        if (params->copy_src.loc.buf.addr && params->copy_dest.buf.addr)
116
            blit(params->copy_src.size.x, params->copy_src.size.y, 3,
117
                 params->copy_dest.buf.addr, params->copy_dest.pos.x,
118
                 params->copy_dest.pos.y, params->copy_dest.buf.stride,
119
                 params->copy_src.loc.buf.addr, params->copy_src.loc.pos.x,
120
                 params->copy_src.loc.pos.y, params->copy_src.loc.buf.stride);
121
        if (params->fill_dest.loc.buf.addr)
122
            blendcolor(params->fill_dest.size.x, params->fill_dest.size.y, params->fill_color,
123
                       params->fill_dest.loc.buf.addr, params->fill_dest.loc.pos.x,
124
                       params->fill_dest.loc.pos.y, params->fill_dest.loc.buf.stride,
125
                       params->fill_dest.loc.buf.addr, params->fill_dest.loc.pos.x,
126
                       params->fill_dest.loc.pos.y, params->fill_dest.loc.buf.stride);
127
        if (params->bg_opacity && params->bg_src.loc.buf.addr && params->bg_dest.buf.addr)
128
            blenda(params->bg_src.size.x, params->bg_src.size.y, params->bg_opacity,
129
                   params->bg_dest.buf.addr, params->bg_dest.pos.x,
130
                   params->bg_dest.pos.y, params->bg_dest.buf.stride,
131
                   params->bg_dest.buf.addr, params->bg_dest.pos.x,
132
                   params->bg_dest.pos.y, params->bg_dest.buf.stride,
133
                   params->bg_src.loc.buf.addr, params->bg_src.loc.pos.x,
134
                   params->bg_src.loc.pos.y, params->bg_src.loc.buf.stride);
135
    }
136
    void* buf = params->viewport.loc.buf.addr;
137
    int stride = params->viewport.loc.buf.stride;
138
    int x = params->viewport.loc.pos.x;
139
    int y = params->viewport.loc.pos.y;
140
    int w = params->viewport.size.x;
141
    int h = params->viewport.size.y;
142
    int spi = data->info->actionhandler->stepsperitem(data);
143
    int dir = 1;
144
    int pos = spi / 2;
145
    int vpos = rdata->viewposition;
146
    int iiv = params->iconsinview;
147
    const struct chooser_renderer_iconflow_itemdata* iparams;
148
    const struct chooser_item* item = data->info->items;
149
    while (true)
150
    {
703 theseven 151
        if (item == selected && dir == 1)
527 theseven 152
        {
153
            dir = -1;
154
            item = &data->info->items[data->info->itemcount - 1];
155
            pos = spi * data->info->itemcount - spi / 2;
156
        }
157
        iparams = (const struct chooser_renderer_iconflow_itemdata*)(item->renderparams);
158
        const struct libui_surface* icon;
703 theseven 159
        if (item == selected) icon = &iparams->icon_selected;
527 theseven 160
        else icon = &iparams->icon;
820 theseven 161
        int ix, iy, io, tx = 0, ty = 0;
527 theseven 162
        int dist = pos - vpos;
163
        chooser_renderer_iconflow_geticondata(x, y, w, h, spi * iiv, dist, icon, &ix, &iy, &io);
703 theseven 164
        if (item == selected)
527 theseven 165
        {
166
            io = 255;
167
            if (iparams->text && iparams->text_color)
820 theseven 168
            {
169
                tx = params->text_pos.x - strlen(iparams->text) * get_font_width() / 2;
170
                ty = params->text_pos.y;
832 theseven 171
                rendertext(buf, tx, ty, stride, iparams->text_color, iparams->text_bgcolor, iparams->text);
820 theseven 172
           }
527 theseven 173
        }
174
        if (icon->loc.buf.addr && io && ix >= x && iy >= y
175
         && ix + icon->size.x <= x + w && iy + icon->size.y <= y + h)
176
            blenda(icon->size.x, icon->size.y, io, buf, ix, iy, stride, buf, ix, iy, stride,
177
                   icon->loc.buf.addr, icon->loc.pos.x, icon->loc.pos.y, icon->loc.buf.stride);
820 theseven 178
        if (iparams->render) iparams->render(data, item, item == selected, ix, iy, io, tx, ty);
703 theseven 179
        if (item == selected) break;
527 theseven 180
        item += dir;
181
        pos += dir * spi;
182
    }
183
    if (params->preblit && params->preblit(data)) return rc;
184
    displaylcd(params->blit_dest.x, params->blit_dest.y, params->blit_src.size.x,
185
               params->blit_src.size.y, params->blit_src.loc.buf.addr, params->blit_src.loc.pos.x,
186
               params->blit_src.loc.pos.y, params->blit_src.loc.buf.stride);
187
    if (params->postblit) params->postblit(data);
188
    return rc;
189
}
190
 
191
static const struct chooser_item* chooser_renderer_iconflow_itematpixel(struct chooser_data* data,
192
                                                                        int x, int y)
193
{
194
    if (x < 0 || y < 0) return NULL;
195
    const struct chooser_renderer_iconflow_params* params;
196
    params = (const struct chooser_renderer_iconflow_params*)(data->info->rendererparams);
197
    if (x >= params->viewport.size.x || y >= params->viewport.size.y) return NULL;
703 theseven 198
    const struct chooser_item* selected = data->selected;
527 theseven 199
    struct chooser_renderer_iconflow_data* rdata;
200
    rdata = (struct chooser_renderer_iconflow_data*)(data->rendererdata);
201
    const struct chooser_item* result = NULL;
202
    int vx = params->viewport.loc.pos.x;
203
    int vy = params->viewport.loc.pos.y;
204
    int vw = params->viewport.size.x;
205
    int vh = params->viewport.size.y;
206
    int spi = data->info->actionhandler->stepsperitem(data);
207
    int dir = 1;
208
    int pos = spi / 2;
209
    int vpos = rdata->viewposition;
210
    int iiv = params->iconsinview;
211
    const struct chooser_renderer_iconflow_itemdata* iparams;
212
    const struct chooser_item* item = data->info->items;
213
    while (true)
214
    {
703 theseven 215
        if (item == selected && dir == 1)
527 theseven 216
        {
217
            dir = -1;
218
            item = &data->info->items[data->info->itemcount - 1];
219
            pos = spi * data->info->itemcount - spi / 2;
220
        }
221
        iparams = (const struct chooser_renderer_iconflow_itemdata*)(item->renderparams);
222
        const struct libui_surface* icon;
703 theseven 223
        if (item == selected) icon = &iparams->icon_selected;
527 theseven 224
        else icon = &iparams->icon;
225
        int ix, iy, o;
226
        int dist = pos - vpos;
227
        chooser_renderer_iconflow_geticondata(vx, vy, vw, vh, spi * iiv, dist, icon, &ix, &iy, &o);
228
        if (x >= ix && y >= ix && x < ix + icon->size.x && y < iy + icon->size.y) result = item;
703 theseven 229
        if (item == selected) break;
527 theseven 230
        item += dir;
231
        pos += dir * spi;
232
    }
233
    return result;
234
}
235
 
236
static void chooser_renderer_iconflow_destroy(struct chooser_data* data)
237
{
238
    free(data->rendererdata);
239
}
240
 
241
 
242
const struct chooser_renderer chooser_renderer_iconflow = 
243
{
244
    .version = CHOOSER_RENDERER_VERSION,
245
    .init = chooser_renderer_iconflow_init,
246
    .render = chooser_renderer_iconflow_render,
247
    .itematpixel = chooser_renderer_iconflow_itematpixel,
248
    .destroy = chooser_renderer_iconflow_destroy
249
};