| Index: libs/ui/export/libui.h | 
| — | — | @@ -48,9 +48,12 @@ | 
| 49 | 49 |  
 | 
| 50 | 50 |  struct libui_api
 | 
| 51 | 51 |  {
 | 
| 52 |   | -    typeof(blend)* blend;
 | 
|   | 52 | +    typeof(fill)* fill;
 | 
|   | 53 | +    typeof(blit)* blit;
 | 
| 53 | 54 |      typeof(blendcolor)* blendcolor;
 | 
| 54 | 55 |      typeof(mattecolor)* mattecolor;
 | 
|   | 56 | +    typeof(blend)* blend;
 | 
|   | 57 | +    typeof(blend)* blenda;
 | 
| 55 | 58 |      typeof(chooser_run)* chooser_run;
 | 
| 56 | 59 |      typeof(chooser_action_handler_wheel)* chooser_action_handler_wheel;
 | 
| 57 | 60 |      typeof(chooser_renderer_list)* chooser_renderer_list;
 | 
| Index: libs/ui/chooser.h | 
| — | — | @@ -80,7 +80,7 @@ | 
| 81 | 81 |      const struct chooser_renderer* renderer;
 | 
| 82 | 82 |      const void* rendererparams;
 | 
| 83 | 83 |      const void* userparams;
 | 
| 84 |   | -    int tickinterval;
 | 
|   | 84 | +    long tickinterval;
 | 
| 85 | 85 |      int itemcount;
 | 
| 86 | 86 |      int defaultitem;
 | 
| 87 | 87 |      const struct chooser_item items[];
 | 
| Index: libs/ui/chooser_renderer_list.c | 
| — | — | @@ -99,13 +99,13 @@ | 
| 100 | 100 |                     params->copy_src.loc.buf.addr, params->copy_src.loc.pos.x,
 | 
| 101 | 101 |                     params->copy_src.loc.pos.y, params->copy_src.loc.buf.stride);
 | 
| 102 | 102 |          if (params->bg_opacity && params->bg_dest.buf.addr && params->bg_src.loc.buf.addr)
 | 
| 103 |   | -            blend(params->bg_src.size.x, params->bg_src.size.y, params->bg_opacity,
 | 
| 104 |   | -                  params->bg_dest.buf.addr, params->bg_dest.pos.x,
 | 
| 105 |   | -                  params->bg_dest.pos.y, params->bg_dest.buf.stride,
 | 
| 106 |   | -                  params->bg_dest.buf.addr, params->bg_dest.pos.x,
 | 
| 107 |   | -                  params->bg_dest.pos.y, params->bg_dest.buf.stride,
 | 
| 108 |   | -                  params->bg_src.loc.buf.addr, params->bg_src.loc.pos.x,
 | 
| 109 |   | -                  params->bg_src.loc.pos.y, params->bg_src.loc.buf.stride);
 | 
|   | 103 | +            blenda(params->bg_src.size.x, params->bg_src.size.y, params->bg_opacity,
 | 
|   | 104 | +                   params->bg_dest.buf.addr, params->bg_dest.pos.x,
 | 
|   | 105 | +                   params->bg_dest.pos.y, params->bg_dest.buf.stride,
 | 
|   | 106 | +                   params->bg_dest.buf.addr, params->bg_dest.pos.x,
 | 
|   | 107 | +                   params->bg_dest.pos.y, params->bg_dest.buf.stride,
 | 
|   | 108 | +                   params->bg_src.loc.buf.addr, params->bg_src.loc.pos.x,
 | 
|   | 109 | +                   params->bg_src.loc.pos.y, params->bg_src.loc.buf.stride);
 | 
| 110 | 110 |      }
 | 
| 111 | 111 |      else if (params->copy_dest.buf.stride == params->bg_dest.buf.stride
 | 
| 112 | 112 |       && params->bg_src.loc.buf.addr && params->copy_dest.buf.addr == params->bg_dest.buf.addr
 | 
| — | — | @@ -114,13 +114,13 @@ | 
| 115 | 115 |       && params->copy_src.size.x == params->bg_src.size.x && params->copy_dest.buf.addr
 | 
| 116 | 116 |       && params->copy_src.size.y == params->bg_src.size.y && params->bg_opacity)
 | 
| 117 | 117 |      {
 | 
| 118 |   | -        blend(params->copy_src.size.x, params->copy_src.size.y, params->bg_opacity,
 | 
| 119 |   | -              params->copy_dest.buf.addr, params->copy_dest.pos.x,
 | 
| 120 |   | -              params->copy_dest.pos.y, params->copy_dest.buf.stride,
 | 
| 121 |   | -              params->copy_src.loc.buf.addr, params->copy_src.loc.pos.x,
 | 
| 122 |   | -              params->copy_src.loc.pos.y, params->copy_src.loc.buf.stride,
 | 
| 123 |   | -              params->bg_src.loc.buf.addr, params->bg_src.loc.pos.x,
 | 
| 124 |   | -              params->bg_src.loc.pos.y, params->bg_src.loc.buf.stride);
 | 
|   | 118 | +        blenda(params->copy_src.size.x, params->copy_src.size.y, params->bg_opacity,
 | 
|   | 119 | +               params->copy_dest.buf.addr, params->copy_dest.pos.x,
 | 
|   | 120 | +               params->copy_dest.pos.y, params->copy_dest.buf.stride,
 | 
|   | 121 | +               params->copy_src.loc.buf.addr, params->copy_src.loc.pos.x,
 | 
|   | 122 | +               params->copy_src.loc.pos.y, params->copy_src.loc.buf.stride,
 | 
|   | 123 | +               params->bg_src.loc.buf.addr, params->bg_src.loc.pos.x,
 | 
|   | 124 | +               params->bg_src.loc.pos.y, params->bg_src.loc.buf.stride);
 | 
| 125 | 125 |      }
 | 
| 126 | 126 |      else
 | 
| 127 | 127 |      {
 | 
| — | — | @@ -137,13 +137,13 @@ | 
| 138 | 138 |                         params->fill_dest.loc.buf.addr, params->fill_dest.loc.pos.x,
 | 
| 139 | 139 |                         params->fill_dest.loc.pos.y, params->fill_dest.loc.buf.stride);
 | 
| 140 | 140 |          if (params->bg_opacity && params->bg_src.loc.buf.addr && params->bg_dest.buf.addr)
 | 
| 141 |   | -            blend(params->bg_src.size.x, params->bg_src.size.y, params->bg_opacity,
 | 
| 142 |   | -                  params->bg_dest.buf.addr, params->bg_dest.pos.x,
 | 
| 143 |   | -                  params->bg_dest.pos.y, params->bg_dest.buf.stride,
 | 
| 144 |   | -                  params->bg_dest.buf.addr, params->bg_dest.pos.x,
 | 
| 145 |   | -                  params->bg_dest.pos.y, params->bg_dest.buf.stride,
 | 
| 146 |   | -                  params->bg_src.loc.buf.addr, params->bg_src.loc.pos.x,
 | 
| 147 |   | -                  params->bg_src.loc.pos.y, params->bg_src.loc.buf.stride);
 | 
|   | 141 | +            blenda(params->bg_src.size.x, params->bg_src.size.y, params->bg_opacity,
 | 
|   | 142 | +                   params->bg_dest.buf.addr, params->bg_dest.pos.x,
 | 
|   | 143 | +                   params->bg_dest.pos.y, params->bg_dest.buf.stride,
 | 
|   | 144 | +                   params->bg_dest.buf.addr, params->bg_dest.pos.x,
 | 
|   | 145 | +                   params->bg_dest.pos.y, params->bg_dest.buf.stride,
 | 
|   | 146 | +                   params->bg_src.loc.buf.addr, params->bg_src.loc.pos.x,
 | 
|   | 147 | +                   params->bg_src.loc.pos.y, params->bg_src.loc.buf.stride);
 | 
| 148 | 148 |      }
 | 
| 149 | 149 |      void* buf = params->viewport.loc.buf.addr;
 | 
| 150 | 150 |      int stride = params->viewport.loc.buf.stride;
 | 
| — | — | @@ -176,9 +176,9 @@ | 
| 177 | 177 |                         buf, x + iparams->fill_box.pos.x, y + iparams->fill_box.pos.y, stride,
 | 
| 178 | 178 |                         buf, x + iparams->fill_box.pos.x, y + iparams->fill_box.pos.y, stride);
 | 
| 179 | 179 |          if (icon->loc.buf.addr && icon_opacity)
 | 
| 180 |   | -            blend(icon->size.x, icon->size.y, icon_opacity,
 | 
| 181 |   | -                  buf, x + iparams->icon_pos.x, y + iparams->icon_pos.y, stride,
 | 
| 182 |   | -                  buf, x + iparams->icon_pos.x, y + iparams->icon_pos.y, stride);
 | 
|   | 180 | +            blenda(icon->size.x, icon->size.y, icon_opacity,
 | 
|   | 181 | +                   buf, x + iparams->icon_pos.x, y + iparams->icon_pos.y, stride,
 | 
|   | 182 | +                   buf, x + iparams->icon_pos.x, y + iparams->icon_pos.y, stride);
 | 
| 183 | 183 |          if (iparams->text && iparams->text_color)
 | 
| 184 | 184 |              rendertext(buf, x + iparams->text_pos.x, y + iparams->text_pos.y,
 | 
| 185 | 185 |                         stride, text_color, 0, iparams->text);
 | 
| Index: libs/ui/blend.c | 
| — | — | @@ -25,36 +25,42 @@ | 
| 26 | 26 |  #include "blend.h"
 | 
| 27 | 27 |  
 | 
| 28 | 28 |  
 | 
| 29 |   | -void blend(int width, int height, int opacity,
 | 
| 30 |   | -           void* outbuf, int outx, int outy, int outstride,
 | 
| 31 |   | -           void* in1buf, int in1x, int in1y, int in1stride,
 | 
| 32 |   | -           void* in2buf, int in2x, int in2y, int in2stride)
 | 
|   | 29 | +void fill(int width, int height, uint32_t color,
 | 
|   | 30 | +          void* buf, int outx, int outy, int stride)
 | 
| 33 | 31 |  {
 | 
| 34 |   | -    char* in1 = (char*)in1buf + (in1x + in1y * in1stride) * 3;
 | 
| 35 |   | -    char* in2 = (char*)in2buf + (in2x + in2y * in2stride) * 4;
 | 
| 36 |   | -    char* out = (char*)outbuf + (outx + outy * outstride) * 3;
 | 
|   | 32 | +    char* out = (char*)buf + (outx + outy * stride) * 3;
 | 
|   | 33 | +    int r = (color >> 0) & 0xff;
 | 
|   | 34 | +    int g = (color >> 8) & 0xff;
 | 
|   | 35 | +    int b = (color >> 16) & 0xff;
 | 
| 37 | 36 |      int x, y;
 | 
| 38 | 37 |      for (y = 0; y < height; y++)
 | 
| 39 | 38 |      {
 | 
| 40 | 39 |          for (x = 0; x < width; x++)
 | 
| 41 | 40 |          {
 | 
| 42 |   | -            int r1 = *in1++;
 | 
| 43 |   | -            int g1 = *in1++;
 | 
| 44 |   | -            int b1 = *in1++;
 | 
| 45 |   | -            int r2 = *in2++;
 | 
| 46 |   | -            int g2 = *in2++;
 | 
| 47 |   | -            int b2 = *in2++;
 | 
| 48 |   | -            int a = *in2++ * opacity;
 | 
| 49 |   | -            *out++ = (a * r2 + (65535 - a) * r1) >> 16;
 | 
| 50 |   | -            *out++ = (a * g2 + (65535 - a) * g1) >> 16;
 | 
| 51 |   | -            *out++ = (a * b2 + (65535 - a) * b1) >> 16;
 | 
|   | 41 | +            *out++ = r;
 | 
|   | 42 | +            *out++ = g;
 | 
|   | 43 | +            *out++ = b;
 | 
| 52 | 44 |          }
 | 
| 53 |   | -        in1 += (in1stride - width) * 3;
 | 
| 54 |   | -        in2 += (in2stride - width) * 4;
 | 
| 55 |   | -        out += (outstride - width) * 3;
 | 
|   | 45 | +        out += (stride - width) * 3;
 | 
| 56 | 46 |      }
 | 
| 57 | 47 |  }
 | 
| 58 | 48 |  
 | 
|   | 49 | +void blit(int width, int height, int pixelbytes,
 | 
|   | 50 | +          void* outbuf, int outx, int outy, int outstride,
 | 
|   | 51 | +          void* inbuf, int inx, int iny, int instride)
 | 
|   | 52 | +{
 | 
|   | 53 | +    int i;
 | 
|   | 54 | +    char* in = (char*)inbuf + (inx + iny * instride) * pixelbytes;
 | 
|   | 55 | +    char* out = (char*)outbuf + (outx + outy * outstride) * pixelbytes;
 | 
|   | 56 | +    int rowsize = width * pixelbytes;
 | 
|   | 57 | +    while (height--)
 | 
|   | 58 | +    {
 | 
|   | 59 | +        memcpy(out, in, rowsize);
 | 
|   | 60 | +        in += instride * pixelbytes;
 | 
|   | 61 | +        out += outstride * pixelbytes;
 | 
|   | 62 | +    }
 | 
|   | 63 | +}
 | 
|   | 64 | +
 | 
| 59 | 65 |  void blendcolor(int width, int height, uint32_t color,
 | 
| 60 | 66 |                  void* outbuf, int outx, int outy, int outstride,
 | 
| 61 | 67 |                  void* inbuf, int inx, int iny, int instride)
 | 
| — | — | @@ -106,38 +112,61 @@ | 
| 107 | 113 |      }
 | 
| 108 | 114 |  }
 | 
| 109 | 115 |  
 | 
| 110 |   | -void blit(int width, int height, int pixelbytes,
 | 
| 111 |   | -          void* outbuf, int outx, int outy, int outstride,
 | 
| 112 |   | -          void* inbuf, int inx, int iny, int instride)
 | 
|   | 116 | +void blend(int width, int height, int opacity,
 | 
|   | 117 | +           void* outbuf, int outx, int outy, int outstride,
 | 
|   | 118 | +           void* in1buf, int in1x, int in1y, int in1stride,
 | 
|   | 119 | +           void* in2buf, int in2x, int in2y, int in2stride)
 | 
| 113 | 120 |  {
 | 
| 114 |   | -    int i;
 | 
| 115 |   | -    char* in = (char*)inbuf + (inx + iny * instride) * pixelbytes;
 | 
| 116 |   | -    char* out = (char*)outbuf + (outx + outy * outstride) * pixelbytes;
 | 
| 117 |   | -    int rowsize = width * pixelbytes;
 | 
| 118 |   | -    while (height--)
 | 
|   | 121 | +    char* in1 = (char*)in1buf + (in1x + in1y * in1stride) * 3;
 | 
|   | 122 | +    char* in2 = (char*)in2buf + (in2x + in2y * in2stride) * 3;
 | 
|   | 123 | +    char* out = (char*)outbuf + (outx + outy * outstride) * 3;
 | 
|   | 124 | +    int x, y;
 | 
|   | 125 | +    for (y = 0; y < height; y++)
 | 
| 119 | 126 |      {
 | 
| 120 |   | -        memcpy(out, in, rowsize);
 | 
| 121 |   | -        in += instride * pixelbytes;
 | 
| 122 |   | -        out += outstride * pixelbytes;
 | 
|   | 127 | +        for (x = 0; x < width; x++)
 | 
|   | 128 | +        {
 | 
|   | 129 | +            int r1 = *in1++;
 | 
|   | 130 | +            int g1 = *in1++;
 | 
|   | 131 | +            int b1 = *in1++;
 | 
|   | 132 | +            int r2 = *in2++;
 | 
|   | 133 | +            int g2 = *in2++;
 | 
|   | 134 | +            int b2 = *in2++;
 | 
|   | 135 | +            *out++ = (opacity * r2 + (255 - opacity) * r1) >> 8;
 | 
|   | 136 | +            *out++ = (opacity * g2 + (255 - opacity) * g1) >> 8;
 | 
|   | 137 | +            *out++ = (opacity * b2 + (255 - opacity) * b1) >> 8;
 | 
|   | 138 | +        }
 | 
|   | 139 | +        in1 += (in1stride - width) * 3;
 | 
|   | 140 | +        in2 += (in2stride - width) * 3;
 | 
|   | 141 | +        out += (outstride - width) * 3;
 | 
| 123 | 142 |      }
 | 
| 124 | 143 |  }
 | 
| 125 | 144 |  
 | 
| 126 |   | -void fill(int width, int height, uint32_t color,
 | 
| 127 |   | -          void* buf, int outx, int outy, int stride)
 | 
|   | 145 | +void blenda(int width, int height, int opacity,
 | 
|   | 146 | +           void* outbuf, int outx, int outy, int outstride,
 | 
|   | 147 | +           void* in1buf, int in1x, int in1y, int in1stride,
 | 
|   | 148 | +           void* in2buf, int in2x, int in2y, int in2stride)
 | 
| 128 | 149 |  {
 | 
| 129 |   | -    char* out = (char*)buf + (outx + outy * stride) * 3;
 | 
| 130 |   | -    int r = (color >> 0) & 0xff;
 | 
| 131 |   | -    int g = (color >> 8) & 0xff;
 | 
| 132 |   | -    int b = (color >> 16) & 0xff;
 | 
|   | 150 | +    char* in1 = (char*)in1buf + (in1x + in1y * in1stride) * 3;
 | 
|   | 151 | +    char* in2 = (char*)in2buf + (in2x + in2y * in2stride) * 4;
 | 
|   | 152 | +    char* out = (char*)outbuf + (outx + outy * outstride) * 3;
 | 
| 133 | 153 |      int x, y;
 | 
| 134 | 154 |      for (y = 0; y < height; y++)
 | 
| 135 | 155 |      {
 | 
| 136 | 156 |          for (x = 0; x < width; x++)
 | 
| 137 | 157 |          {
 | 
| 138 |   | -            *out++ = r;
 | 
| 139 |   | -            *out++ = g;
 | 
| 140 |   | -            *out++ = b;
 | 
|   | 158 | +            int r1 = *in1++;
 | 
|   | 159 | +            int g1 = *in1++;
 | 
|   | 160 | +            int b1 = *in1++;
 | 
|   | 161 | +            int r2 = *in2++;
 | 
|   | 162 | +            int g2 = *in2++;
 | 
|   | 163 | +            int b2 = *in2++;
 | 
|   | 164 | +            int a = *in2++ * opacity;
 | 
|   | 165 | +            *out++ = (a * r2 + (65535 - a) * r1) >> 16;
 | 
|   | 166 | +            *out++ = (a * g2 + (65535 - a) * g1) >> 16;
 | 
|   | 167 | +            *out++ = (a * b2 + (65535 - a) * b1) >> 16;
 | 
| 141 | 168 |          }
 | 
| 142 |   | -        out += (stride - width) * 3;
 | 
|   | 169 | +        in1 += (in1stride - width) * 3;
 | 
|   | 170 | +        in2 += (in2stride - width) * 4;
 | 
|   | 171 | +        out += (outstride - width) * 3;
 | 
| 143 | 172 |      }
 | 
| 144 | 173 |  }
 | 
| Index: libs/ui/main.c | 
| — | — | @@ -27,9 +27,12 @@ | 
| 28 | 28 |  
 | 
| 29 | 29 |  struct libui_api apitable =
 | 
| 30 | 30 |  {
 | 
| 31 |   | -    .blend = blend,
 | 
|   | 31 | +    .fill = fill,
 | 
|   | 32 | +    .blit = blit,
 | 
| 32 | 33 |      .blendcolor = blendcolor,
 | 
| 33 | 34 |      .mattecolor = mattecolor,
 | 
|   | 35 | +    .blend = blend,
 | 
|   | 36 | +    .blenda = blenda,
 | 
| 34 | 37 |      .chooser_run = chooser_run,
 | 
| 35 | 38 |      .chooser_action_handler_wheel = &chooser_action_handler_wheel,
 | 
| 36 | 39 |      .chooser_renderer_list = &chooser_renderer_list,
 | 
| Index: libs/ui/chooser_renderer_iconflow.c | 
| — | — | @@ -1,237 +1,237 @@ | 
| 2 |   | -//
 | 
| 3 |   | -//
 | 
| 4 |   | -//    Copyright 2011 TheSeven
 | 
| 5 |   | -//
 | 
| 6 |   | -//
 | 
| 7 |   | -//    This file is part of emCORE.
 | 
| 8 |   | -//
 | 
| 9 |   | -//    emCORE is free software: you can redistribute it and/or
 | 
| 10 |   | -//    modify it under the terms of the GNU General Public License as
 | 
| 11 |   | -//    published by the Free Software Foundation, either version 2 of the
 | 
| 12 |   | -//    License, or (at your option) any later version.
 | 
| 13 |   | -//
 | 
| 14 |   | -//    emCORE is distributed in the hope that it will be useful,
 | 
| 15 |   | -//    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
| 16 |   | -//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | 
| 17 |   | -//    See the GNU General Public License for more details.
 | 
| 18 |   | -//
 | 
| 19 |   | -//    You should have received a copy of the GNU General Public License along
 | 
| 20 |   | -//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
 | 
| 21 |   | -//
 | 
| 22 |   | -//
 | 
| 23 |   | -
 | 
| 24 |   | -
 | 
| 25 |   | -#include "emcorelib.h"
 | 
| 26 |   | -#include "libui.h"
 | 
| 27 |   | -#include "chooser.h"
 | 
| 28 |   | -#include "chooser_renderer_iconflow.h"
 | 
| 29 |   | -
 | 
| 30 |   | -
 | 
| 31 |   | -static int chooser_renderer_iconflow_init(struct chooser_data* data)
 | 
| 32 |   | -{
 | 
| 33 |   | -    const struct chooser_renderer_iconflow_params* params;
 | 
| 34 |   | -    params = (const struct chooser_renderer_iconflow_params*)(data->info->rendererparams);
 | 
| 35 |   | -    if (params->version != CHOOSER_RENDERER_ICONFLOW_PARAMS_VERSION) return -1;
 | 
| 36 |   | -    data->rendererdata = malloc(sizeof(struct chooser_renderer_iconflow_data));
 | 
| 37 |   | -    if (!data->rendererdata) return -2;
 | 
| 38 |   | -    struct chooser_renderer_iconflow_data* rdata;
 | 
| 39 |   | -    rdata = (struct chooser_renderer_iconflow_data*)(data->rendererdata);
 | 
| 40 |   | -    rdata->viewposition = params->startposition * data->info->actionhandler->stepsperitem(data);
 | 
| 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 |   | -            blend(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 |   | -        blend(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 |   | -            blend(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 |   | -            blend(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 |   | -};
 | 
|   | 2 | +// | 
|   | 3 | +// | 
|   | 4 | +//    Copyright 2011 TheSeven | 
|   | 5 | +// | 
|   | 6 | +// | 
|   | 7 | +//    This file is part of emCORE. | 
|   | 8 | +// | 
|   | 9 | +//    emCORE is free software: you can redistribute it and/or | 
|   | 10 | +//    modify it under the terms of the GNU General Public License as | 
|   | 11 | +//    published by the Free Software Foundation, either version 2 of the | 
|   | 12 | +//    License, or (at your option) any later version. | 
|   | 13 | +// | 
|   | 14 | +//    emCORE is distributed in the hope that it will be useful, | 
|   | 15 | +//    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|   | 16 | +//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 
|   | 17 | +//    See the GNU General Public License for more details. | 
|   | 18 | +// | 
|   | 19 | +//    You should have received a copy of the GNU General Public License along | 
|   | 20 | +//    with emCORE.  If not, see <http://www.gnu.org/licenses/>. | 
|   | 21 | +// | 
|   | 22 | +// | 
|   | 23 | + | 
|   | 24 | + | 
|   | 25 | +#include "emcorelib.h" | 
|   | 26 | +#include "libui.h" | 
|   | 27 | +#include "chooser.h" | 
|   | 28 | +#include "chooser_renderer_iconflow.h" | 
|   | 29 | + | 
|   | 30 | + | 
|   | 31 | +static int chooser_renderer_iconflow_init(struct chooser_data* data) | 
|   | 32 | +{ | 
|   | 33 | +    const struct chooser_renderer_iconflow_params* params; | 
|   | 34 | +    params = (const struct chooser_renderer_iconflow_params*)(data->info->rendererparams); | 
|   | 35 | +    if (params->version != CHOOSER_RENDERER_ICONFLOW_PARAMS_VERSION) return -1; | 
|   | 36 | +    data->rendererdata = malloc(sizeof(struct chooser_renderer_iconflow_data)); | 
|   | 37 | +    if (!data->rendererdata) return -2; | 
|   | 38 | +    struct chooser_renderer_iconflow_data* rdata; | 
|   | 39 | +    rdata = (struct chooser_renderer_iconflow_data*)(data->rendererdata); | 
|   | 40 | +    rdata->viewposition = params->startposition * data->info->actionhandler->stepsperitem(data); | 
|   | 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 | +}; | 
| Index: libs/ui/blend.h | 
| — | — | @@ -28,10 +28,11 @@ | 
| 29 | 29 |  #include "libui.h"
 | 
| 30 | 30 |  
 | 
| 31 | 31 |  
 | 
| 32 |   | -void blend(int width, int height, int opacity,
 | 
| 33 |   | -           void* outbuf, int outx, int outy, int outstride,
 | 
| 34 |   | -           void* in1buf, int in1x, int in1y, int in1stride,
 | 
| 35 |   | -           void* in2buf, int in2x, int in2y, int in2stride);
 | 
|   | 32 | +void fill(int width, int height, uint32_t color,
 | 
|   | 33 | +          void* buf, int x, int y, int stride);
 | 
|   | 34 | +void blit(int width, int height, int pixelbytes,
 | 
|   | 35 | +          void* outbuf, int outx, int outy, int outstride,
 | 
|   | 36 | +          void* inbuf, int inx, int iny, int instride);
 | 
| 36 | 37 |  void blendcolor(int width, int height, uint32_t color,
 | 
| 37 | 38 |                  void* outbuf, int outx, int outy, int outstride,
 | 
| 38 | 39 |                  void* inbuf, int inx, int iny, int instride);
 | 
| — | — | @@ -38,11 +39,14 @@ | 
| 39 | 40 |  void mattecolor(int width, int height, uint32_t color,
 | 
| 40 | 41 |                  void* outbuf, int outx, int outy, int outstride,
 | 
| 41 | 42 |                  void* inbuf, int inx, int iny, int instride);
 | 
| 42 |   | -void blit(int width, int height, int pixelbytes,
 | 
| 43 |   | -          void* outbuf, int outx, int outy, int outstride,
 | 
| 44 |   | -          void* inbuf, int inx, int iny, int instride);
 | 
| 45 |   | -void fill(int width, int height, uint32_t color,
 | 
| 46 |   | -          void* buf, int x, int y, int stride);
 | 
|   | 43 | +void blend(int width, int height, int opacity,
 | 
|   | 44 | +           void* outbuf, int outx, int outy, int outstride,
 | 
|   | 45 | +           void* in1buf, int in1x, int in1y, int in1stride,
 | 
|   | 46 | +           void* in2buf, int in2x, int in2y, int in2stride);
 | 
|   | 47 | +void blenda(int width, int height, int opacity,
 | 
|   | 48 | +            void* outbuf, int outx, int outy, int outstride,
 | 
|   | 49 | +            void* in1buf, int in1x, int in1y, int in1stride,
 | 
|   | 50 | +            void* in2buf, int in2x, int in2y, int in2stride);
 | 
| 47 | 51 |  
 | 
| 48 | 52 |  
 | 
| 49 | 53 |  #endif
 |