Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2009 Vincent Sanders <vince@simtec.co.uk>
  3.  *
  4.  * This file is part of libnsfb, http://www.netsurf-browser.org/
  5.  * Licenced under the MIT License,
  6.  *                http://www.opensource.org/licenses/mit-license.php
  7.  */
  8.  
  9. #include <stdbool.h>
  10. #include <endian.h>
  11. #include <stdlib.h>
  12.  
  13. #include "libnsfb.h"
  14. #include "libnsfb_plot.h"
  15. #include "libnsfb_plot_util.h"
  16.  
  17. #include "nsfb.h"
  18. #include "plot.h"
  19.  
  20. static inline uint8_t *
  21. get_xy_loc(nsfb_t *nsfb, int x, int y)
  22. {
  23.         return (uint8_t *)(nsfb->ptr + (y * nsfb->linelen) + (x * 3));
  24. }
  25.  
  26. #if __BYTE_ORDER == __BIG_ENDIAN
  27. static inline nsfb_colour_t pixel_to_colour(uint8_t pixel)
  28. {
  29.         return (pixel >> 8) & ~0xFF000000U;
  30. }
  31.  
  32. /* convert a colour value to a 32bpp pixel value ready for screen output */
  33. static inline uint32_t colour_to_pixel(nsfb_colour_t c)
  34. {
  35.         return (c << 8);
  36. }
  37. #else /* __BYTE_ORDER == __BIG_ENDIAN */
  38. static inline nsfb_colour_t pixel_to_colour(uint32_t pixel)
  39. {
  40.         return ((pixel & 0xFF) << 16) |
  41.                 ((pixel & 0xFF00)) |
  42.                 ((pixel & 0xFF0000) >> 16);
  43. }
  44.  
  45. /* convert a colour value to a 32bpp pixel value ready for screen output */
  46. static inline uint32_t colour_to_pixel(nsfb_colour_t c)
  47. {
  48.         return ((c & 0xff0000) >> 16) | (c & 0xff00) | ((c & 0xff) << 16);
  49. }
  50. #endif
  51.  
  52. #define SIGN(x)  ((x<0) ?  -1  :  ((x>0) ? 1 : 0))
  53.  
  54. static bool
  55. line(nsfb_t *nsfb, int linec, nsfb_bbox_t *line, nsfb_plot_pen_t *pen)
  56. {
  57.         int w;
  58.         uint32_t ent;
  59.         uint32_t *pvideo;
  60.         int x, y, i;
  61.         int dx, dy, sdy;
  62.         int dxabs, dyabs;
  63.  
  64.         ent = colour_to_pixel(pen->stroke_colour);
  65.  
  66.         for (;linec > 0; linec--) {
  67.  
  68.                 if (line->y0 == line->y1) {
  69.                         /* horizontal line special cased */
  70.  
  71.                         if (!nsfb_plot_clip_ctx(nsfb, line)) {
  72.                                 /* line outside clipping */
  73.                                 line++;
  74.                                 continue;
  75.                         }
  76.  
  77.                         pvideo = get_xy_loc(nsfb, line->x0, line->y0);
  78.  
  79.                         w = line->x1 - line->x0;
  80.                         while (w-- > 0)
  81.                                 *(pvideo + w) = ent;
  82.  
  83.                 } else {
  84.                         /* standard bresenham line */
  85.  
  86.                         if (!nsfb_plot_clip_line_ctx(nsfb, line)) {
  87.                                 /* line outside clipping */
  88.                                 line++;
  89.                                 continue;
  90.                         }
  91.  
  92.                         /* the horizontal distance of the line */
  93.                         dx = line->x1 - line->x0;
  94.                         dxabs = abs (dx);
  95.  
  96.                         /* the vertical distance of the line */
  97.                         dy = line->y1 - line->y0;
  98.                         dyabs = abs (dy);
  99.  
  100.                         sdy = dx ? SIGN(dy) * SIGN(dx) : SIGN(dy);
  101.  
  102.                         if (dx >= 0)
  103.                                 pvideo = get_xy_loc(nsfb, line->x0, line->y0);
  104.                         else
  105.                                 pvideo = get_xy_loc(nsfb, line->x1, line->y1);
  106.  
  107.                         x = dyabs >> 1;
  108.                         y = dxabs >> 1;
  109.  
  110.                         if (dxabs >= dyabs) {
  111.                                 /* the line is more horizontal than vertical */
  112.                                 for (i = 0; i < dxabs; i++) {
  113.                                         *pvideo = ent;
  114.  
  115.                                         pvideo++;
  116.                                         y += dyabs;
  117.                                         if (y >= dxabs) {
  118.                                                 y -= dxabs;
  119.                                                 pvideo += sdy * (nsfb->linelen>>2);
  120.                                         }
  121.                                 }
  122.                         } else {
  123.                                 /* the line is more vertical than horizontal */
  124.                                 for (i = 0; i < dyabs; i++) {
  125.                                         *pvideo = ent;
  126.                                         pvideo += sdy * (nsfb->linelen >> 2);
  127.  
  128.                                         x += dxabs;
  129.                                         if (x >= dyabs) {
  130.                                                 x -= dyabs;
  131.                                                 pvideo++;
  132.                                         }
  133.                                 }
  134.                         }
  135.  
  136.                 }
  137.                 line++;
  138.         }
  139.         return true;
  140. }
  141.  
  142.  
  143.  
  144. static bool fill(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t c)
  145. {
  146.         int w;
  147.         uint32_t *pvid;
  148.         uint32_t ent;
  149.         uint32_t llen;
  150.         uint32_t width;
  151.         uint32_t height;
  152.  
  153.         if (!nsfb_plot_clip_ctx(nsfb, rect))
  154.                 return true; /* fill lies outside current clipping region */
  155.  
  156.         ent = colour_to_pixel(c);
  157.         width = rect->x1 - rect->x0;
  158.         height = rect->y1 - rect->y0;
  159.         llen = (nsfb->linelen >> 2) - width;
  160.  
  161.         pvid = get_xy_loc(nsfb, rect->x0, rect->y0);
  162.  
  163.         while (height-- > 0) {
  164.                 w = width;
  165.                 while (w >= 16) {
  166.                        *pvid++ = ent; *pvid++ = ent;
  167.                        *pvid++ = ent; *pvid++ = ent;
  168.                        *pvid++ = ent; *pvid++ = ent;
  169.                        *pvid++ = ent; *pvid++ = ent;
  170.                        *pvid++ = ent; *pvid++ = ent;
  171.                        *pvid++ = ent; *pvid++ = ent;
  172.                        *pvid++ = ent; *pvid++ = ent;
  173.                        *pvid++ = ent; *pvid++ = ent;
  174.                        w-=16;
  175.                 }
  176.                 while (w >= 4) {
  177.                        *pvid++ = ent; *pvid++ = ent;
  178.                        *pvid++ = ent; *pvid++ = ent;
  179.                        w-=4;
  180.                 }
  181.                 while (w > 0) {
  182.                        *pvid++ = ent;
  183.                        w--;
  184.                 }
  185.                 pvid += llen;
  186.         }
  187.  
  188.         return true;
  189. }
  190.  
  191.  
  192.  
  193.  
  194. static bool point(nsfb_t *nsfb, int x, int y, nsfb_colour_t c)
  195. {
  196.         uint32_t *pvideo;
  197.  
  198.         /* check point lies within clipping region */
  199.         if ((x < nsfb->clip.x0) ||
  200.             (x >= nsfb->clip.x1) ||
  201.             (y < nsfb->clip.y0) ||
  202.             (y >= nsfb->clip.y1))
  203.                 return true;
  204.  
  205.         pvideo = get_xy_loc(nsfb, x, y);
  206.  
  207.         if ((c & 0xFF000000) != 0) {
  208.                 if ((c & 0xFF000000) != 0xFF000000) {
  209.                         c = nsfb_plot_ablend(c, pixel_to_colour(*pvideo));
  210.                 }
  211.  
  212.                 *pvideo = colour_to_pixel(c);
  213.         }
  214.         return true;
  215. }
  216.  
  217. static bool
  218. glyph1(nsfb_t *nsfb,
  219.        nsfb_bbox_t *loc,
  220.        const uint8_t *pixel,
  221.        int pitch,
  222.        nsfb_colour_t c)
  223. {
  224.         uint32_t *pvideo;
  225.         int xloop, yloop;
  226.         int xoff, yoff; /* x and y offset into image */
  227.         int x = loc->x0;
  228.         int y = loc->y0;
  229.         int width = loc->x1 - loc->x0;
  230.         int height = loc->y1 - loc->y0;
  231.         uint32_t fgcol;
  232.         const uint8_t *fntd;
  233.         uint8_t row;
  234.  
  235.         if (!nsfb_plot_clip_ctx(nsfb, loc))
  236.                 return true;
  237.  
  238.         if (height > (loc->y1 - loc->y0))
  239.                 height = (loc->y1 - loc->y0);
  240.  
  241.         if (width > (loc->x1 - loc->x0))
  242.                 width = (loc->x1 - loc->x0);
  243.  
  244.         xoff = loc->x0 - x;
  245.         yoff = loc->y0 - y;
  246.  
  247.         pvideo = get_xy_loc(nsfb, loc->x0, loc->y0);
  248.  
  249.         fgcol = colour_to_pixel(c);
  250.  
  251.         for (yloop = yoff; yloop < height; yloop++) {
  252.                 fntd = pixel + (yloop * (pitch>>3)) + (xoff>>3);
  253.                 row = (*fntd++) << (xoff & 3);
  254.                 for (xloop = xoff; xloop < width ; xloop++) {
  255.                         if (((xloop % 8) == 0) && (xloop != 0)) {
  256.                                 row = *fntd++;
  257.                         }
  258.  
  259.                         if ((row & 0x80) != 0) {
  260.                                 *(pvideo + xloop) = fgcol;
  261.                         }
  262.                         row = row << 1;
  263.  
  264.                 }
  265.  
  266.                 pvideo += (nsfb->linelen >> 2);
  267.         }
  268.  
  269.         return true;
  270. }
  271.  
  272. static bool
  273. glyph8(nsfb_t *nsfb,
  274.        nsfb_bbox_t *loc,
  275.        const uint8_t *pixel,
  276.        int pitch,
  277.        nsfb_colour_t c)
  278. {
  279.         uint32_t *pvideo;
  280.         nsfb_colour_t abpixel; /* alphablended pixel */
  281.         int xloop, yloop;
  282.         int xoff, yoff; /* x and y offset into image */
  283.         int x = loc->x0;
  284.         int y = loc->y0;
  285.         int width = loc->x1 - loc->x0;
  286.         int height = loc->y1 - loc->y0;
  287.         uint32_t fgcol;
  288.  
  289.         if (!nsfb_plot_clip_ctx(nsfb, loc))
  290.                 return true;
  291.  
  292.         if (height > (loc->y1 - loc->y0))
  293.                 height = (loc->y1 - loc->y0);
  294.  
  295.         if (width > (loc->x1 - loc->x0))
  296.                 width = (loc->x1 - loc->x0);
  297.  
  298.         xoff = loc->x0 - x;
  299.         yoff = loc->y0 - y;
  300.  
  301.         pvideo = get_xy_loc(nsfb, loc->x0, loc->y0);
  302.  
  303.         fgcol = c & 0xFFFFFF;
  304.  
  305.         for (yloop = 0; yloop < height; yloop++) {
  306.                 for (xloop = 0; xloop < width; xloop++) {
  307.                         abpixel = (pixel[((yoff + yloop) * pitch) + xloop + xoff] << 24) | fgcol;
  308.                         if ((abpixel & 0xFF000000) != 0) {
  309.                                 /* pixel is not transparent */
  310.                                 if ((abpixel & 0xFF000000) != 0xFF000000) {
  311.                                         abpixel = nsfb_plot_ablend(abpixel,
  312.                                                                    pixel_to_colour(*(pvideo + xloop)));
  313.                                 }
  314.  
  315.                                 *(pvideo + xloop) = colour_to_pixel(abpixel);
  316.                         }
  317.                 }
  318.                 pvideo += (nsfb->linelen >> 2);
  319.         }
  320.  
  321.         return true;
  322. }
  323.  
  324. static bool
  325. bitmap(nsfb_t *nsfb,
  326.        const nsfb_bbox_t *loc,
  327.        const nsfb_colour_t *pixel,
  328.        int bmp_width,
  329.        int bmp_height,
  330.        int bmp_stride,
  331.        bool alpha)
  332. {
  333.         uint32_t *pvideo;
  334.         nsfb_colour_t abpixel = 0; /* alphablended pixel */
  335.         int xloop, yloop;
  336.         int xoff, yoff; /* x and y offset into image */
  337.         int x = loc->x0;
  338.         int y = loc->y0;
  339.         int width = loc->x1 - loc->x0;
  340.         int height = loc->y1 - loc->y0;
  341.         nsfb_bbox_t clipped; /* clipped display */
  342.  
  343.         /* TODO here we should scale the image from bmp_width to width, for
  344.          * now simply crop.
  345.          */
  346.         if (width > bmp_width)
  347.                 width = bmp_width;
  348.  
  349.         if (height > bmp_height)
  350.                 height = bmp_height;
  351.  
  352.         /* The part of the scaled image actually displayed is cropped to the
  353.          * current context.
  354.          */
  355.         clipped.x0 = x;
  356.         clipped.y0 = y;
  357.         clipped.x1 = x + width;
  358.         clipped.y1 = y + height;
  359.  
  360.         if (!nsfb_plot_clip_ctx(nsfb, &clipped)) {
  361.                 return true;
  362.         }
  363.  
  364.         if (height > (clipped.y1 - clipped.y0))
  365.                 height = (clipped.y1 - clipped.y0);
  366.  
  367.         if (width > (clipped.x1 - clipped.x0))
  368.                 width = (clipped.x1 - clipped.x0);
  369.  
  370.         xoff = clipped.x0 - x;
  371.         yoff = (clipped.y0 - y) * bmp_width;
  372.         height = height * bmp_stride + yoff;
  373.  
  374.         /* plot the image */
  375.         pvideo = get_xy_loc(nsfb, clipped.x0, clipped.y0);
  376.  
  377.         if (alpha) {
  378.                 for (yloop = yoff; yloop < height; yloop += bmp_stride) {
  379.                         for (xloop = 0; xloop < width; xloop++) {
  380.                                 abpixel = pixel[yloop + xloop + xoff];
  381.                                 if ((abpixel & 0xFF000000) != 0) {
  382.                                         if ((abpixel & 0xFF000000) != 0xFF000000) {
  383.                                                 abpixel = nsfb_plot_ablend(abpixel,
  384.                                                                            pixel_to_colour(*(pvideo + xloop)));
  385.                                         }
  386.  
  387.                                         *(pvideo + xloop) = colour_to_pixel(abpixel);
  388.                                 }
  389.                         }
  390.                         pvideo += (nsfb->linelen >> 2);
  391.                 }
  392.         } else {
  393.                 for (yloop = yoff; yloop < height; yloop += bmp_stride) {
  394.                         for (xloop = 0; xloop < width; xloop++) {
  395.                                 abpixel = pixel[yloop + xloop + xoff];
  396.                                 *(pvideo + xloop) = colour_to_pixel(abpixel);
  397.                         }
  398.                         pvideo += (nsfb->linelen >> 2);
  399.                 }
  400.         }
  401.         return true;
  402. }
  403.  
  404. static bool readrect(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t *buffer)
  405. {
  406.         uint32_t *pvideo;
  407.         int xloop, yloop;
  408.         int width;
  409.  
  410.         if (!nsfb_plot_clip_ctx(nsfb, rect)) {
  411.                 return true;
  412.         }
  413.  
  414.         width = rect->x1 - rect->x0;
  415.  
  416.         pvideo = get_xy_loc(nsfb, rect->x0, rect->y0);
  417.  
  418.         for (yloop = rect->y0; yloop < rect->y1; yloop += 1) {
  419.                 for (xloop = 0; xloop < width; xloop++) {
  420.                         *buffer = pixel_to_colour(*(pvideo + xloop));
  421.                         buffer++;
  422.                 }
  423.                 pvideo += (nsfb->linelen >> 2);
  424.         }
  425.         return true;
  426. }
  427.  
  428. const nsfb_plotter_fns_t _nsfb_24bpp_plotters = {
  429.         .line = line,
  430.         .fill = fill,
  431.         .point = point,
  432.         .bitmap = bitmap,
  433.         .glyph8 = glyph8,
  434.         .glyph1 = glyph1,
  435.         .readrect = readrect,
  436. };
  437.  
  438. /*
  439.  * Local Variables:
  440.  * c-basic-offset:8
  441.  * End:
  442.  */
  443.