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.  * Copyright 2010 Michael Drake <tlsa@netsurf-browser.org>
  4.  *
  5.  * Plot code common to all bpp just with differing types
  6.  *
  7.  * This file is part of libnsfb, http://www.netsurf-browser.org/
  8.  * Licenced under the MIT License,
  9.  *                http://www.opensource.org/licenses/mit-license.php
  10.  */
  11.  
  12. #ifndef PLOT_TYPE
  13. #error PLOT_TYPE must be set to uint8_t, uint16_t, or uint32_t
  14. #endif
  15. #ifndef PLOT_LINELEN
  16. #error PLOT_LINELEN must be a macro to increment a line length
  17. #endif
  18.  
  19. #include "palette.h"
  20.  
  21. #define SIGN(x)  ((x<0) ?  -1  :  ((x>0) ? 1 : 0))
  22.  
  23. static bool
  24. line(nsfb_t *nsfb, int linec, nsfb_bbox_t *line, nsfb_plot_pen_t *pen)
  25. {
  26.         int w;
  27.         PLOT_TYPE ent;
  28.         PLOT_TYPE *pvideo;
  29.         int x, y, i;
  30.         int dx, dy, sdy;
  31.         int dxabs, dyabs;
  32.  
  33.         ent = colour_to_pixel(nsfb, pen->stroke_colour);
  34.  
  35.         for (;linec > 0; linec--) {
  36.  
  37.                 if (line->y0 == line->y1) {
  38.                         /* horizontal line special cased */
  39.  
  40.                         if (!nsfb_plot_clip_ctx(nsfb, line)) {
  41.                                 /* line outside clipping */
  42.                                 line++;
  43.                                 continue;
  44.                         }
  45.  
  46.                         pvideo = get_xy_loc(nsfb, line->x0, line->y0);
  47.  
  48.                         w = line->x1 - line->x0;
  49.                         while (w-- > 0)
  50.                                 *(pvideo + w) = ent;
  51.  
  52.                 } else {
  53.                         /* standard bresenham line */
  54.  
  55.                         if (!nsfb_plot_clip_line_ctx(nsfb, line)) {
  56.                                 /* line outside clipping */
  57.                                 line++;
  58.                                 continue;
  59.                         }
  60.  
  61.                         /* the horizontal distance of the line */
  62.                         dx = line->x1 - line->x0;
  63.                         dxabs = abs (dx);
  64.  
  65.                         /* the vertical distance of the line */
  66.                         dy = line->y1 - line->y0;
  67.                         dyabs = abs (dy);
  68.  
  69.                         sdy = dx ? SIGN(dy) * SIGN(dx) : SIGN(dy);
  70.  
  71.                         if (dx >= 0)
  72.                                 pvideo = get_xy_loc(nsfb, line->x0, line->y0);
  73.                         else
  74.                                 pvideo = get_xy_loc(nsfb, line->x1, line->y1);
  75.  
  76.                         x = dyabs >> 1;
  77.                         y = dxabs >> 1;
  78.  
  79.                         if (dxabs >= dyabs) {
  80.                                 /* the line is more horizontal than vertical */
  81.                                 for (i = 0; i < dxabs; i++) {
  82.                                         *pvideo = ent;
  83.  
  84.                                         pvideo++;
  85.                                         y += dyabs;
  86.                                         if (y >= dxabs) {
  87.                                                 y -= dxabs;
  88.                                                 pvideo += sdy * PLOT_LINELEN(nsfb->linelen);
  89.                                         }
  90.                                 }
  91.                         } else {
  92.                                 /* the line is more vertical than horizontal */
  93.                                 for (i = 0; i < dyabs; i++) {
  94.                                         *pvideo = ent;
  95.                                         pvideo += sdy * PLOT_LINELEN(nsfb->linelen);
  96.  
  97.                                         x += dxabs;
  98.                                         if (x >= dyabs) {
  99.                                                 x -= dyabs;
  100.                                                 pvideo++;
  101.                                         }
  102.                                 }
  103.                         }
  104.  
  105.                 }
  106.                 line++;
  107.         }
  108.         return true;
  109. }
  110.  
  111.  
  112. static bool point(nsfb_t *nsfb, int x, int y, nsfb_colour_t c)
  113. {
  114.         PLOT_TYPE *pvideo;
  115.  
  116.         /* check point lies within clipping region */
  117.         if ((x < nsfb->clip.x0) ||
  118.             (x >= nsfb->clip.x1) ||
  119.             (y < nsfb->clip.y0) ||
  120.             (y >= nsfb->clip.y1))
  121.                 return true;
  122.  
  123.         pvideo = get_xy_loc(nsfb, x, y);
  124.  
  125.         if ((c & 0xFF000000) != 0) {
  126.                 if ((c & 0xFF000000) != 0xFF000000) {
  127.                         c = nsfb_plot_ablend(c, pixel_to_colour(nsfb, *pvideo));
  128.                 }
  129.  
  130.                 *pvideo = colour_to_pixel(nsfb, c);
  131.         }
  132.         return true;
  133. }
  134.  
  135. static bool
  136. glyph1(nsfb_t *nsfb,
  137.        nsfb_bbox_t *loc,
  138.        const uint8_t *pixel,
  139.        int pitch,
  140.        nsfb_colour_t c)
  141. {
  142.         PLOT_TYPE *pvideo;
  143.         PLOT_TYPE const *pvideo_limit;
  144.         PLOT_TYPE fgcol;
  145.         int xloop;
  146.         int xoff, yoff; /* x and y offset into image */
  147.         int x = loc->x0;
  148.         int y = loc->y0;
  149.         int width;
  150.         int height;
  151.         const size_t line_len = PLOT_LINELEN(nsfb->linelen);
  152.         const int first_col = 1 << (loc->x1 - loc->x0 - 1);
  153.         const uint8_t *row;
  154.  
  155.         if (!nsfb_plot_clip_ctx(nsfb, loc))
  156.                 return true;
  157.  
  158.         height = loc->y1 - y;
  159.         width = loc->x1 - x;
  160.  
  161.         xoff = loc->x0 - x;
  162.         yoff = loc->y0 - y;
  163.  
  164.         fgcol = colour_to_pixel(nsfb, c);
  165.  
  166.         pitch >>= 3; /* bits to bytes */
  167.  
  168.         pvideo = get_xy_loc(nsfb, x, loc->y0);
  169.         pvideo_limit = pvideo + line_len * (height - yoff);
  170.         row = pixel + yoff * pitch;
  171.  
  172.         for (; pvideo < pvideo_limit; pvideo += line_len) {
  173.                 for (xloop = xoff; xloop < width; xloop++) {
  174.  
  175.                         if ((*row & (first_col >> xloop)) != 0) {
  176.                                 *(pvideo + xloop) = fgcol;
  177.                         }
  178.                 }
  179.                 row += pitch;
  180.         }
  181.  
  182.         return true;
  183. }
  184.  
  185. static bool
  186. glyph8(nsfb_t *nsfb,
  187.        nsfb_bbox_t *loc,
  188.        const uint8_t *pixel,
  189.        int pitch,
  190.        nsfb_colour_t c)
  191. {
  192.         PLOT_TYPE *pvideo;
  193.         nsfb_colour_t fgcol;
  194.         nsfb_colour_t abpixel; /* alphablended pixel */
  195.         int xloop, yloop;
  196.         int xoff, yoff; /* x and y offset into image */
  197.         int x = loc->x0;
  198.         int y = loc->y0;
  199.         int width;
  200.         int height;
  201.  
  202.         if (!nsfb_plot_clip_ctx(nsfb, loc))
  203.                 return true;
  204.  
  205.         height = (loc->y1 - loc->y0);
  206.         width = (loc->x1 - loc->x0);
  207.  
  208.         xoff = loc->x0 - x;
  209.         yoff = loc->y0 - y;
  210.  
  211.         pvideo = get_xy_loc(nsfb, loc->x0, loc->y0);
  212.  
  213.         fgcol = c & 0xFFFFFF;
  214.  
  215.         for (yloop = 0; yloop < height; yloop++) {
  216.                 for (xloop = 0; xloop < width; xloop++) {
  217.                         abpixel = (pixel[((yoff + yloop) * pitch) + xloop + xoff] << 24) | fgcol;
  218.                         if ((abpixel & 0xFF000000) != 0) {
  219.                                 /* pixel is not transparent */
  220.                                 if ((abpixel & 0xFF000000) != 0xFF000000) {
  221.                                         abpixel = nsfb_plot_ablend(abpixel,
  222.                                                                    pixel_to_colour(nsfb, *(pvideo + xloop)));
  223.                                 }
  224.  
  225.                                 *(pvideo + xloop) = colour_to_pixel(nsfb, abpixel);
  226.                         }
  227.                 }
  228.                 pvideo += PLOT_LINELEN(nsfb->linelen);
  229.         }
  230.  
  231.         return true;
  232. }
  233.  
  234. static bool bitmap_scaled(nsfb_t *nsfb, const nsfb_bbox_t *loc,
  235.                 const nsfb_colour_t *pixel, int bmp_width, int bmp_height,
  236.                 int bmp_stride, bool alpha)
  237. {
  238.         PLOT_TYPE *pvideo;
  239.         PLOT_TYPE *pvideo_limit;
  240.         nsfb_colour_t abpixel; /* alphablended pixel */
  241.         int xloop;
  242.         int xoff, yoff, xoffs; /* x and y offsets into image */
  243.         int x = loc->x0;
  244.         int y = loc->y0;
  245.         int width = loc->x1 - loc->x0; /* size to scale to */
  246.         int height = loc->y1 - loc->y0; /* size to scale to */
  247.         int rheight, rwidth; /* post-clipping render area dimensions */
  248.         int dx, dy; /* scale factor (integer part) */
  249.         int dxr, dyr; /* scale factor (remainder) */
  250.         int rx, ry, rxs; /* remainder trackers */
  251.         nsfb_bbox_t clipped; /* clipped display */
  252.  
  253.         /* The part of the scaled image actually displayed is cropped to the
  254.          * current context. */
  255.         clipped.x0 = x;
  256.         clipped.y0 = y;
  257.         clipped.x1 = x + width;
  258.         clipped.y1 = y + height;
  259.  
  260.         if (!nsfb_plot_clip_ctx(nsfb, &clipped))
  261.                 return true;
  262.  
  263.         /* get height of rendering region, after clipping */
  264.         if (height > (clipped.y1 - clipped.y0))
  265.                 rheight = (clipped.y1 - clipped.y0);
  266.         else
  267.                 rheight = height;
  268.  
  269.         /* get width of rendering region, after clipping */
  270.         if (width > (clipped.x1 - clipped.x0))
  271.                 rwidth = (clipped.x1 - clipped.x0);
  272.         else
  273.                 rwidth = width;
  274.  
  275.         if (nsfb->palette != NULL) {
  276.                 nsfb_palette_dither_init(nsfb->palette, rwidth);
  277.         }
  278.  
  279.         /* get veritcal (y) and horizontal (x) scale factors; both integer
  280.          * part and remainder */
  281.         dx = bmp_width / width;
  282.         dy = (bmp_height / height) * bmp_stride;
  283.         dxr = bmp_width % width;
  284.         dyr = bmp_height % height;
  285.  
  286.         /* get start offsets to part of image being scaled, after clipping and
  287.          * set remainder trackers to correct starting value */
  288.         if (clipped.x0 - x != 0) {
  289.                 xoffs = ((clipped.x0 - x) * bmp_width) / width;
  290.                 rxs = ((clipped.x0 - x) * bmp_width) % width;
  291.         } else {
  292.                 xoffs = 0;
  293.                 rxs = 0;
  294.         }
  295.         if (clipped.y0 - y != 0) {
  296.                 yoff = (((clipped.y0 - y) * bmp_height) / height) * bmp_stride;
  297.                 ry = ((clipped.y0 - y) * bmp_height) % height;
  298.         } else {
  299.                 yoff = 0;
  300.                 ry = 0;
  301.         }
  302.  
  303.         /* plot the image */
  304.         pvideo = get_xy_loc(nsfb, clipped.x0, clipped.y0);
  305.         pvideo_limit = pvideo + PLOT_LINELEN(nsfb->linelen) * rheight;
  306.         if (alpha) {
  307.                 for (; pvideo < pvideo_limit;
  308.                                 pvideo += PLOT_LINELEN(nsfb->linelen)) {
  309.                         /* looping through render area vertically */
  310.                         xoff = xoffs;
  311.                         rx = rxs;
  312.                         for (xloop = 0; xloop < rwidth; xloop++) {
  313.                                 /* looping through render area horizontally */
  314.                                 /* get value of source pixel in question */
  315.                                 abpixel = pixel[yoff + xoff];
  316.                                 if ((abpixel & 0xFF000000) != 0) {
  317.                                         /* pixel is not transparent; have to
  318.                                          * plot something */
  319.                                         if ((abpixel & 0xFF000000) !=
  320.                                                         0xFF000000) {
  321.                                                 /* pixel is not opaque; need to
  322.                                                  * blend */
  323.                                                 abpixel = nsfb_plot_ablend(
  324.                                                                 abpixel,
  325.                                                                 pixel_to_colour(
  326.                                                                 nsfb,
  327.                                                                 *(pvideo +
  328.                                                                 xloop)));
  329.                                         }
  330.                                         /* plot pixel */
  331.                                         *(pvideo + xloop) = colour_to_pixel(
  332.                                                         nsfb, abpixel);
  333.                                 }
  334.                                 /* handle horizontal interpolation */
  335.                                 xoff += dx;
  336.                                 rx += dxr;
  337.                                 if (rx >= width) {
  338.                                         xoff++;
  339.                                         rx -= width;
  340.                                 }
  341.                         }
  342.                         /* handle vertical interpolation */
  343.                         yoff += dy;
  344.                         ry += dyr;
  345.                         if (ry >= height) {
  346.                                 yoff += bmp_stride;
  347.                                 ry -= height;
  348.                         }
  349.                 }
  350.         } else {
  351.                 for (; pvideo < pvideo_limit;
  352.                                 pvideo += PLOT_LINELEN(nsfb->linelen)) {
  353.                         /* looping through render area vertically */
  354.                         xoff = xoffs;
  355.                         rx = rxs;
  356.                         for (xloop = 0; xloop < rwidth; xloop++) {
  357.                                 /* looping through render area horizontally */
  358.                                 /* get value of source pixel in question */
  359.                                 abpixel = pixel[yoff + xoff];
  360.                                 /* plot pixel */
  361.                                 *(pvideo + xloop) = colour_to_pixel(
  362.                                                 nsfb, abpixel);
  363.  
  364.                                 /* handle horizontal interpolation */
  365.                                 xoff += dx;
  366.                                 rx += dxr;
  367.                                 if (rx >= width) {
  368.                                         xoff++;
  369.                                         rx -= width;
  370.                                 }
  371.                         }
  372.                         /* handle vertical interpolation */
  373.                         yoff += dy;
  374.                         ry += dyr;
  375.                         if (ry >= height) {
  376.                                 yoff += bmp_stride;
  377.                                 ry -= height;
  378.                         }
  379.                 }
  380.         }
  381.  
  382.         if (nsfb->palette != NULL) {
  383.                 nsfb_palette_dither_fini(nsfb->palette);
  384.         }
  385.  
  386.         return true;
  387. }
  388.  
  389. static bool
  390. bitmap(nsfb_t *nsfb,
  391.        const nsfb_bbox_t *loc,
  392.        const nsfb_colour_t *pixel,
  393.        int bmp_width,
  394.        int bmp_height,
  395.        int bmp_stride,
  396.        bool alpha)
  397. {
  398.         PLOT_TYPE *pvideo;
  399.         nsfb_colour_t abpixel; /* alphablended pixel */
  400.         int xloop, yloop;
  401.         int xoff, yoff; /* x and y offset into image */
  402.         int x = loc->x0;
  403.         int y = loc->y0;
  404.         int width = loc->x1 - loc->x0;
  405.         int height = loc->y1 - loc->y0;
  406.         nsfb_bbox_t clipped; /* clipped display */
  407.  
  408.         if (width == 0 || height == 0)
  409.                 return true;
  410.  
  411.         /* Scaled bitmaps are handled by a separate function */
  412.         if (width != bmp_width || height != bmp_height)
  413.                 return bitmap_scaled(nsfb, loc, pixel, bmp_width, bmp_height,
  414.                                 bmp_stride, alpha);
  415.  
  416.         /* The part of the image actually displayed is cropped to the
  417.          * current context. */
  418.         clipped.x0 = x;
  419.         clipped.y0 = y;
  420.         clipped.x1 = x + width;
  421.         clipped.y1 = y + height;
  422.  
  423.         if (!nsfb_plot_clip_ctx(nsfb, &clipped))
  424.                 return true;
  425.  
  426.         if (height > (clipped.y1 - clipped.y0))
  427.                 height = (clipped.y1 - clipped.y0);
  428.  
  429.         if (width > (clipped.x1 - clipped.x0))
  430.                 width = (clipped.x1 - clipped.x0);
  431.  
  432.         if (nsfb->palette != NULL) {
  433.                 nsfb_palette_dither_init(nsfb->palette, width);
  434.         }
  435.  
  436.         xoff = clipped.x0 - x;
  437.         yoff = (clipped.y0 - y) * bmp_stride;
  438.         height = height * bmp_stride + yoff;
  439.  
  440.         /* plot the image */
  441.         pvideo = get_xy_loc(nsfb, clipped.x0, clipped.y0);
  442.  
  443.         if (alpha) {
  444.                 for (yloop = yoff; yloop < height; yloop += bmp_stride) {
  445.                         for (xloop = 0; xloop < width; xloop++) {
  446.                                 abpixel = pixel[yloop + xloop + xoff];
  447.                                 if ((abpixel & 0xFF000000) != 0) {
  448.                                         /* pixel is not transparent; have to
  449.                                          * plot something */
  450.                                         if ((abpixel & 0xFF000000) !=
  451.                                                        0xFF000000) {
  452.                                                 /* pixel is not opaque; need to
  453.                                                  * blend */
  454.                                                 abpixel = nsfb_plot_ablend(
  455.                                                                 abpixel,
  456.                                                                 pixel_to_colour(
  457.                                                                 nsfb,
  458.                                                                 *(pvideo +
  459.                                                                 xloop)));
  460.                                         }
  461.  
  462.                                         *(pvideo + xloop) = colour_to_pixel(
  463.                                                         nsfb, abpixel);
  464.                                 }
  465.                         }
  466.                         pvideo += PLOT_LINELEN(nsfb->linelen);
  467.                 }
  468.         } else {
  469.                 for (yloop = yoff; yloop < height; yloop += bmp_stride) {
  470.                         for (xloop = 0; xloop < width; xloop++) {
  471.                                 abpixel = pixel[yloop + xloop + xoff];
  472.                                 *(pvideo + xloop) = colour_to_pixel(
  473.                                                 nsfb, abpixel);
  474.                         }
  475.                         pvideo += PLOT_LINELEN(nsfb->linelen);
  476.                 }
  477.         }
  478.  
  479.         if (nsfb->palette != NULL) {
  480.                 nsfb_palette_dither_fini(nsfb->palette);
  481.         }
  482.  
  483.         return true;
  484. }
  485.  
  486. static bool readrect(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t *buffer)
  487. {
  488.         PLOT_TYPE *pvideo;
  489.         int xloop, yloop;
  490.         int width;
  491.  
  492.         if (!nsfb_plot_clip_ctx(nsfb, rect)) {
  493.                 return true;
  494.         }
  495.  
  496.         width = rect->x1 - rect->x0;
  497.  
  498.         pvideo = get_xy_loc(nsfb, rect->x0, rect->y0);
  499.  
  500.         for (yloop = rect->y0; yloop < rect->y1; yloop += 1) {
  501.                 for (xloop = 0; xloop < width; xloop++) {
  502.                         *buffer = pixel_to_colour(nsfb, *(pvideo + xloop));
  503.                         buffer++;
  504.                 }
  505.                 pvideo += PLOT_LINELEN(nsfb->linelen);
  506.         }
  507.         return true;
  508. }
  509.  
  510.  
  511. /*
  512.  * Local Variables:
  513.  * c-basic-offset:8
  514.  * End:
  515.  */
  516.