Просмотр исходного кода

Merge pull request #36 from yangfasheng/master

update engine
yangfasheng 7 лет назад
Родитель
Сommit
d04b59ce50
5 измененных файлов с 307 добавлено и 39 удалено
  1. 202 19
      src/blit.c
  2. 1 1
      src/color.c
  3. 31 5
      src/image_jpg.c
  4. 21 13
      src/region.c
  5. 52 1
      src/rtgui_driver.c

+ 202 - 19
src/blit.c

@@ -817,10 +817,10 @@ Blit565to565PixelAlpha(struct rtgui_blit_info * info)
                 *(rt_uint16_t*)dstp = (rt_uint16_t)(d | d >> 16);
                 srcp = (rt_uint32_t*)((unsigned int)srcp + 2);
                 dstp = (rt_uint32_t*)((unsigned int)dstp + 2);
-                
+
                 width = (info->dst_w - 1) / 2;
             }
-            
+
             DUFFS_LOOP8(
             {
                 rt_uint32_t s = *srcp++;
@@ -837,7 +837,7 @@ Blit565to565PixelAlpha(struct rtgui_blit_info * info)
                 d = ((s - d) * alpha / 32 + d) & 0x07e0f81f;
                 *dstp++ = (du << 16) | (du >> 16) | d;
             }, width);
-            
+
             /* Deal with the last pixel. */
             if ((addr_align && (info->dst_w - 1) % 2) || (!addr_align && info->dst_w % 2))
             {
@@ -852,7 +852,7 @@ Blit565to565PixelAlpha(struct rtgui_blit_info * info)
                 srcp = (rt_uint32_t*)((unsigned int)srcp + 2);
                 dstp = (rt_uint32_t*)((unsigned int)dstp + 2);
             }
-            
+
             srcp = (rt_uint32_t*)((unsigned int)srcp + info->src_skip);
             dstp = (rt_uint32_t*)((unsigned int)dstp + info->dst_skip);
         }
@@ -883,8 +883,57 @@ static void BlitRGBtoRGBSurfaceAlpha128(struct rtgui_blit_info *info)
     }
 }
 
-/* fast RGB888->(A)RGB888 blending with surface alpha */
+/* fast RGB888->RGB888 blending with surface alpha */
 static void BlitRGBtoRGBSurfaceAlpha(struct rtgui_blit_info *info)
+{
+    unsigned int alpha = info->a;
+
+    if (alpha)
+    {
+        int width = info->dst_w;
+        int height = info->dst_h;
+        rt_uint8_t *srcp = (rt_uint8_t *)info->src;
+        int srcskip = info->src_skip;
+        rt_uint8_t *dstp = (rt_uint8_t *)info->dst;
+        int dstskip = info->dst_skip;
+        int inverse_alpha = 257 - alpha;
+
+        while (height--)
+        {
+            DUFFS_LOOP4(
+            {
+                if (alpha == 255)
+                {
+                    *dstp++ = *(srcp++);
+                    *dstp++ = *(srcp++);
+                    *dstp++ = *(srcp++);
+                    *dstp++ = 255;
+                    srcp++;
+                }
+                else if (alpha)
+                {
+                    *dstp = ((*(srcp)* alpha) + (inverse_alpha * (*dstp))) >> 8;
+                    dstp++;
+                    srcp++;
+                    *dstp = ((*(srcp)* alpha) + (inverse_alpha * (*dstp))) >> 8;
+                    dstp++;
+                    srcp++;
+                    *dstp = ((*(srcp)* alpha) + (inverse_alpha * (*dstp))) >> 8;
+                    dstp++;
+                    srcp++;
+                    *dstp = 255;
+                    dstp++;
+                    srcp++;
+                }
+            }, width);
+            srcp += srcskip;
+            dstp += dstskip;
+        }
+    }
+}
+
+/* fast RGB888->(A)RGB888 blending with surface alpha */
+static void BlitRGBtoARGBSurfaceAlpha(struct rtgui_blit_info *info)
 {
     unsigned int alpha = info->a;
     if(alpha == 128)
@@ -907,23 +956,26 @@ static void BlitRGBtoRGBSurfaceAlpha(struct rtgui_blit_info *info)
             {
                 if (alpha == 255)
                 {
-                    *dstp++ = *(srcp + 2);
-                    *dstp++ = *(srcp + 1);
-                    *dstp++ = *(srcp);
+                    *dstp++ = *(srcp++);
+                    *dstp++ = *(srcp++);
+                    *dstp++ = *(srcp++);
                     *dstp++ = alpha;
-                    srcp += 3;
+                    srcp ++;
                 }
                 else if (alpha)
                 {
-                    *dstp = ((*(srcp + 2) * alpha) + (inverse_alpha * (*dstp))) >> 8;
+                    *dstp = ((*(srcp) * alpha) + (inverse_alpha * (*dstp))) >> 8;
                     dstp++;
-                    *dstp = ((*(srcp + 1) * alpha) + (inverse_alpha * (*dstp))) >> 8;
+                    srcp++;
+                    *dstp = ((*(srcp) * alpha) + (inverse_alpha * (*dstp))) >> 8;
                     dstp++;
+                    srcp++;
                     *dstp = ((*(srcp) * alpha) + (inverse_alpha * (*dstp))) >> 8;
                     dstp++;
+                    srcp++;
                     *dstp = alpha + ((255 - alpha) * (*dstp)) / 255;
                     dstp++;
-                    srcp += 3;
+                    srcp++;
                 }
             }, width);
             srcp += srcskip;
@@ -1007,6 +1059,60 @@ static void BlitAlphato565PixelAlpha(struct rtgui_blit_info * info)
     }
 }
 
+/* RGB888->RGB565 */
+static void BlitRGBto565PixelAlpha(struct rtgui_blit_info * info)
+{
+    int width = info->dst_w;
+    int height = info->dst_h;
+    rt_uint32_t *srcp = (rt_uint32_t *)info->src;
+    int srcskip = info->src_skip >> 2;
+    rt_uint16_t *dstp = (rt_uint16_t *)info->dst;
+    int dstskip = info->dst_skip >> 1;
+
+    while (height--)
+    {
+        /* *INDENT-OFF* */
+        DUFFS_LOOP4(
+        {
+            rt_uint32_t s = *srcp;
+            unsigned alpha = 255;
+            if (info->a > 0 && info->a != 255)
+                alpha = alpha * info->a / 255;
+            alpha = alpha >> 3;	/* downscale alpha to 5 bits */
+            /* FIXME: Here we special-case opaque alpha since the
+               compositioning used (>>8 instead of /255) doesn't handle
+               it correctly. Also special-case alpha=0 for speed?
+               Benchmark this! */
+            if (alpha)
+            {
+                if (alpha == (255 >> 3))
+                {
+                    *dstp = (rt_uint16_t)((s >> 8 & 0xf800) + (s >> 5 & 0x7e0) + (s >> 3 & 0x1f));
+                }
+                else if (alpha > 0)
+                {
+                    rt_uint32_t d = *dstp;
+                    /*
+                     * convert source and destination to G0RAB65565
+                     * and blend all components at the same time
+                     */
+                    s = ((s & 0xfc00) << 11) + (s >> 8 & 0xf800)
+                        + (s >> 3 & 0x1f);
+                    d = (d | d << 16) & 0x07e0f81f;
+                    d += (s - d) * alpha >> 5;
+                    d &= 0x07e0f81f;
+                    *dstp = (rt_uint16_t)(d | d >> 16);
+                }
+            }
+            srcp++;
+            dstp++;
+        }, width);
+        /* *INDENT-ON* */
+        srcp += srcskip;
+        dstp += dstskip;
+    }
+}
+
 /* fast ARGB8888->RGB565 blending with pixel alpha */
 static void BlitARGBto565PixelAlpha(struct rtgui_blit_info * info)
 {
@@ -1116,6 +1222,64 @@ static void BlitARGBtoRGBPixelAlpha(struct rtgui_blit_info *info)
     }
 }
 
+static void BlitAlphatoRGB888PixelAlpha(struct rtgui_blit_info *info)
+{
+    rt_uint32_t srcpixel;
+    rt_uint32_t srcR, srcG, srcB, srcA;
+    rt_uint32_t dstpixel;
+    rt_uint32_t dstR, dstG, dstB;
+
+    srcR = info->r;
+    srcG = info->g;
+    srcB = info->b;
+
+    while (info->dst_h--)
+    {
+        rt_uint8_t *src = (rt_uint8_t *)info->src;
+        rt_uint32_t *dst = (rt_uint32_t *)info->dst;
+        int n = info->dst_w;
+        while (n--)
+        {
+            srcA = (rt_uint8_t)(*src);
+            if (info->a > 0 && info->a != 255)
+                srcA = srcA * info->a / 255;
+            ARGB8888_FROM_RGBA(srcpixel, srcR, srcG, srcB, srcA);
+
+            /* not do alpha blend */
+            if (srcA == 255)
+            {
+                *dst = srcpixel;
+            }
+            else if (srcA >> 3 == 0)
+            {
+                /* keep original pixel data */
+            }
+            else
+            {
+                int alpha = srcA + 1;
+                int inverse_alpha = 257 - alpha;
+
+                dstpixel = *dst;
+                dstR = (rt_uint8_t)(dstpixel >> 16);
+                dstG = (rt_uint8_t)(dstpixel >> 8);
+                dstB = (rt_uint8_t)dstpixel;
+
+                dstR = ((srcR * alpha) + (inverse_alpha * dstR)) >> 8;
+                dstG = ((srcG * alpha) + (inverse_alpha * dstG)) >> 8;
+                dstB = ((srcB * alpha) + (inverse_alpha * dstB)) >> 8;
+
+                *dst = ((rt_uint32_t)0xFF << 24) | ((rt_uint32_t)dstR << 16) | ((rt_uint32_t)dstG << 8) | dstB;
+            }
+
+            ++src;
+            ++dst;
+        }
+
+        info->src += info->src_pitch;
+        info->dst += info->dst_pitch;
+    }
+}
+
 static void BlitAlphatoARGB8888PixelAlpha(struct rtgui_blit_info *info)
 {
     rt_uint32_t srcpixel;
@@ -1320,10 +1484,33 @@ void rtgui_blit(struct rtgui_blit_info * info)
 
     if (info->src_fmt == RTGRAPHIC_PIXEL_FORMAT_RGB565)
     {
-        if (info->dst_fmt == RTGRAPHIC_PIXEL_FORMAT_RGB565)
+        switch (info->dst_fmt)
+        {
+        case RTGRAPHIC_PIXEL_FORMAT_RGB565:
             Blit565to565PixelAlpha(info);
-        else if (info->dst_fmt == RTGRAPHIC_PIXEL_FORMAT_ARGB888)
+            break;
+        case RTGRAPHIC_PIXEL_FORMAT_RGB888:
+            BlitRGB565toARGB8888(info);
+            break;
+        case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
             BlitRGB565toARGB8888(info);
+            break;
+        }
+    }
+    else if (info->src_fmt == RTGRAPHIC_PIXEL_FORMAT_RGB888)
+    {
+        switch (info->dst_fmt)
+        {
+        case RTGRAPHIC_PIXEL_FORMAT_RGB565:
+            BlitRGBto565PixelAlpha(info);
+            break;
+        case RTGRAPHIC_PIXEL_FORMAT_RGB888:
+            BlitRGBtoRGBSurfaceAlpha(info);
+            break;
+        case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
+            BlitRGBtoARGBSurfaceAlpha(info);
+            break;
+        }
     }
     else if (info->src_fmt == RTGRAPHIC_PIXEL_FORMAT_ARGB888)
     {
@@ -1340,11 +1527,6 @@ void rtgui_blit(struct rtgui_blit_info * info)
             break;
         }
     }
-    else if (info->src_fmt == RTGRAPHIC_PIXEL_FORMAT_RGB888)
-    {
-        if (info->dst_fmt == RTGRAPHIC_PIXEL_FORMAT_ARGB888)
-            BlitRGBtoRGBSurfaceAlpha(info);
-    }
     else if (info->src_fmt == RTGRAPHIC_PIXEL_FORMAT_ALPHA)
     {
         switch (info->dst_fmt)
@@ -1353,6 +1535,7 @@ void rtgui_blit(struct rtgui_blit_info * info)
             BlitAlphato565PixelAlpha(info);
             break;
         case RTGRAPHIC_PIXEL_FORMAT_RGB888:
+            BlitAlphatoRGB888PixelAlpha(info);
             break;
         case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
             BlitAlphatoARGB8888PixelAlpha(info);

+ 1 - 1
src/color.c

@@ -43,7 +43,7 @@ const static rt_uint8_t pixel_bits_table[] =
     16, /* RGB565 */
     16, /* BGR565 */
     18, /* RGB666 */
-    24, /* RGB888 */
+    32, /* RGB888 */
     32, /* ARGB888 */
 };
 

+ 31 - 5
src/image_jpg.c

@@ -795,7 +795,11 @@ static rt_bool_t rtgui_image_jpeg_load(struct rtgui_image *image, struct rtgui_f
             jpeg->byte_per_pixel = 2;
         }
         /* else use RGB888 format */
-        else jpeg->byte_per_pixel = 3;
+        else
+        {
+            jpeg->tjpgd.format = 0;
+            jpeg->byte_per_pixel = 3;
+        }
 
         image->w = (rt_uint16_t)jpeg->tjpgd.width;
         image->h = (rt_uint16_t)jpeg->tjpgd.height;
@@ -805,8 +809,12 @@ static rt_bool_t rtgui_image_jpeg_load(struct rtgui_image *image, struct rtgui_f
 
         if (jpeg->is_loaded == RT_TRUE)
         {
-            jpeg->pixels = (rt_uint8_t *)rtgui_malloc(
-                               jpeg->byte_per_pixel * image->w * image->h);
+            rt_uint8_t *pixels = RT_NULL;
+            
+            if (jpeg->tjpgd.format == 0)
+                pixels = (rt_uint8_t *)rtgui_malloc(4 * image->w * image->h);
+
+            jpeg->pixels = (rt_uint8_t *)rtgui_malloc(jpeg->byte_per_pixel * image->w * image->h);
             if (jpeg->pixels == RT_NULL)
             {
                 rt_kprintf("TJPGD err: no mem to load (%d)\n",
@@ -819,6 +827,24 @@ static rt_bool_t rtgui_image_jpeg_load(struct rtgui_image *image, struct rtgui_f
 
             rtgui_filerw_close(jpeg->filerw);
             jpeg->filerw = RT_NULL;
+
+            if (jpeg->tjpgd.format == 0 && pixels)
+            {
+                rt_uint8_t *dstp = pixels, *srcp = jpeg->pixels;
+
+                while (srcp < jpeg->pixels + jpeg->byte_per_pixel * image->w * image->h)
+                {
+                    *dstp++ = *(srcp + 2);
+                    *dstp++ = *(srcp + 1);
+                    *dstp++ = *(srcp);
+                    *dstp++ = 255;
+                    srcp += 3;
+                }
+
+                rtgui_free(jpeg->pixels);
+                jpeg->pixels = pixels;
+                jpeg->byte_per_pixel = 4;
+            }
         }
         res = RT_TRUE;
     }
@@ -932,7 +958,7 @@ static void rtgui_image_jpeg_blit(struct rtgui_image *image,
                 (rtgui_dc_get_pixel_format(dc) == RTGRAPHIC_PIXEL_FORMAT_RGB565 && jpeg->tjpgd.format == 1))
         {
             rt_uint16_t imageWidth = image->w * jpeg->byte_per_pixel;
-            rt_uint8_t *src = jpeg->pixels + yoff * imageWidth + xoff + jpeg->byte_per_pixel;
+            rt_uint8_t *src = jpeg->pixels + yoff * imageWidth + xoff * jpeg->byte_per_pixel;
 
             for (y = 0; y < h; y++)
             {
@@ -954,7 +980,7 @@ static void rtgui_image_jpeg_blit(struct rtgui_image *image,
             info.src = jpeg->pixels + yoff * image->w * jpeg->byte_per_pixel + xoff * jpeg->byte_per_pixel;
             info.src_h = rtgui_rect_height(*dst_rect);
             info.src_w = rtgui_rect_width(*dst_rect);
-            info.src_fmt = (jpeg->tjpgd.format == 0? RTGRAPHIC_PIXEL_FORMAT_RGB888 : RTGRAPHIC_PIXEL_FORMAT_RGB565);
+            info.src_fmt = (jpeg->tjpgd.format == 0 ? RTGRAPHIC_PIXEL_FORMAT_RGB888 : RTGRAPHIC_PIXEL_FORMAT_RGB565);
             info.src_pitch = image->w * jpeg->byte_per_pixel;
             info.src_skip = info.src_pitch - info.src_w * jpeg->byte_per_pixel;
 

+ 21 - 13
src/region.c

@@ -408,7 +408,7 @@ rtgui_region_appendNonO(
 
     newRects = rEnd - r;
 
-    RT_ASSERT(y1 <= y2);
+    RT_ASSERT(y1 < y2);
     RT_ASSERT(newRects != 0);
 
     /* Make sure we have enough space for all rectangles to be added */
@@ -616,7 +616,7 @@ rtgui_op(
             {
                 top = RTGUI_MAX(r1y1, ybot);
                 bot = RTGUI_MIN(r1->y2, r2y1);
-                if (top <= bot)
+                if (top < bot)
                 {
                     curBand = newReg->data->numRects;
                     rtgui_region_appendNonO(newReg, r1, r1BandEnd, top, bot);
@@ -631,7 +631,7 @@ rtgui_op(
             {
                 top = RTGUI_MAX(r2y1, ybot);
                 bot = RTGUI_MIN(r2->y2, r1y1);
-                if (top <= bot)
+                if (top < bot)
                 {
                     curBand = newReg->data->numRects;
                     rtgui_region_appendNonO(newReg, r2, r2BandEnd, top, bot);
@@ -681,21 +681,29 @@ rtgui_op(
     {
         /* Do first nonOverlap1Func call, which may be able to coalesce */
         FindBand(r1, r1BandEnd, r1End, r1y1);
-        curBand = newReg->data->numRects;
-        rtgui_region_appendNonO(newReg, r1, r1BandEnd, RTGUI_MAX(r1y1, ybot), r1->y2);
-        Coalesce(newReg, prevBand, curBand);
-        /* Just append the rest of the boxes  */
-        AppendRegions(newReg, r1BandEnd, r1End);
+
+        if (RTGUI_MAX(r1y1, ybot) < r1->y2)
+        {
+            curBand = newReg->data->numRects;
+            rtgui_region_appendNonO(newReg, r1, r1BandEnd, RTGUI_MAX(r1y1, ybot), r1->y2);
+            Coalesce(newReg, prevBand, curBand);
+            /* Just append the rest of the boxes  */
+            AppendRegions(newReg, r1BandEnd, r1End);
+        }
     }
     else if ((r2 != r2End) && appendNon2)
     {
         /* Do first nonOverlap2Func call, which may be able to coalesce */
         FindBand(r2, r2BandEnd, r2End, r2y1);
-        curBand = newReg->data->numRects;
-        rtgui_region_appendNonO(newReg, r2, r2BandEnd, RTGUI_MAX(r2y1, ybot), r2->y2);
-        Coalesce(newReg, prevBand, curBand);
-        /* Append rest of boxes */
-        AppendRegions(newReg, r2BandEnd, r2End);
+
+        if (RTGUI_MAX(r2y1, ybot) < r2->y2)
+        {
+            curBand = newReg->data->numRects;
+            rtgui_region_appendNonO(newReg, r2, r2BandEnd, RTGUI_MAX(r2y1, ybot), r2->y2);
+            Coalesce(newReg, prevBand, curBand);
+            /* Append rest of boxes */
+            AppendRegions(newReg, r2BandEnd, r2End);
+        }
     }
 
     if (oldData)

+ 52 - 1
src/rtgui_driver.c

@@ -379,6 +379,46 @@ static void _rgb565p_draw_vline(rtgui_color_t *c, int x , int y1, int y2)
     }
 }
 
+static void _rgb888_set_pixel(rtgui_color_t *c, int x, int y)
+{
+    *GET_PIXEL(rtgui_graphic_get_device(), x, y, rtgui_color_t) = *c;
+}
+
+static void _rgb888_get_pixel(rtgui_color_t *c, int x, int y)
+{
+    *c = ((rtgui_color_t)*GET_PIXEL(rtgui_graphic_get_device(), x, y, rtgui_color_t) & 0xFFFFFF) + 0xFF000000;
+}
+
+static void _rgb888_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
+{
+    int index;
+    rtgui_color_t *pixel_ptr;
+
+    /* get pixel pointer in framebuffer */
+    pixel_ptr = GET_PIXEL(rtgui_graphic_get_device(), x1, y, rtgui_color_t);
+
+    for (index = x1; index < x2; index++)
+    {
+        *pixel_ptr = *c;
+        pixel_ptr++;
+    }
+}
+
+static void _rgb888_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
+{
+    struct rtgui_graphic_driver *drv;
+    rtgui_color_t *dst;
+    int index;
+
+    drv = rtgui_graphic_get_device();
+    dst = GET_PIXEL(drv, x, y1, rtgui_color_t);
+    for (index = y1; index < y2; index++)
+    {
+        *dst = *c;
+        dst += drv->width;
+    }
+}
+
 static void _argb888_set_pixel(rtgui_color_t *c, int x, int y)
 {
     *GET_PIXEL(rtgui_graphic_get_device(), x, y, rtgui_color_t) = *c;
@@ -428,7 +468,7 @@ static void framebuffer_draw_raw_hline(rt_uint8_t *pixels, int x1, int x2, int y
     drv = rtgui_graphic_get_device();
     dst = GET_PIXEL(drv, x1, y, rt_uint8_t);
     memcpy(dst, pixels,
-              (x2 - x1) * _UI_BITBYTES(drv->bits_per_pixel));
+           (x2 - x1) * _UI_BITBYTES(drv->bits_per_pixel));
 }
 
 const struct rtgui_graphic_driver_ops _framebuffer_rgb565_ops =
@@ -449,6 +489,15 @@ const struct rtgui_graphic_driver_ops _framebuffer_rgb565p_ops =
     framebuffer_draw_raw_hline,
 };
 
+const struct rtgui_graphic_driver_ops _framebuffer_rgb888_ops =
+{
+    _rgb888_set_pixel,
+    _rgb888_get_pixel,
+    _rgb888_draw_hline,
+    _rgb888_draw_vline,
+    framebuffer_draw_raw_hline,
+};
+
 const struct rtgui_graphic_driver_ops _framebuffer_argb888_ops =
 {
     _argb888_set_pixel,
@@ -554,6 +603,8 @@ const struct rtgui_graphic_driver_ops *rtgui_framebuffer_get_ops(int pixel_forma
         return &_framebuffer_rgb565_ops;
     case RTGRAPHIC_PIXEL_FORMAT_RGB565P:
         return &_framebuffer_rgb565p_ops;
+    case RTGRAPHIC_PIXEL_FORMAT_RGB888:
+        return &_framebuffer_rgb888_ops;
     case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
         return &_framebuffer_argb888_ops;
     default: