Hi, 

I get 32 bit working.I use SDL_HWSURFACE, the amiga GFX Cards use bgra with
that additional funcs.This give lots faster scrolling than SDL_SWSURFACE.
I use a extra define in libnsfb makefile, because its possible that on other
systems the GFX card work in rbga mode.On amiga 68k AOS 
bgra is standard but some cards allow a rgba screen mode, but all users use
BGRA mode,
because some programs have problems to work in rgba mode ok.

the new funcs are only need in bitmap and readrect funcs

if somebody know how can make this funcs faster or other suggestions, please
let know.

the 16 bit plotters code i have not add, because when change 

if (nsfb_set_geometry(nsfb, 0, 0, 32) == -1) {

to 
if (nsfb_set_geometry(nsfb, 0, 0, 16) == -1) {

my system crash.maybe 16 bit is not implement and working ?



#ifdef __BIG_ENDIAN_BGRA__
static inline nsfb_colour_t pixel_to_colour(uint32_t pixel)
{
        return (pixel >> 8) & ~0xFF000000U;
}

/* convert a colour value to a 32bpp pixel value ready for screen output */
static inline uint32_t colour_to_pixel(nsfb_colour_t c)
{
        return (c << 8);
}

// this funcs are need because bitmaps have diffrent format (rgba)when get
from netsurf.
//if your SDL surface work in rgba mode(seem in SDL_SWSURFACE done), you
need diffrent funcs.
static inline nsfb_colour_t nsfb_plot_ablend_rgba(nsfb_colour_t
pixel,nsfb_colour_t  scrpixel)
{
      int opacity = pixel & 0xFF;
      int transp = 0x100 - opacity;
      uint32_t rb, g; 
      pixel >>= 8;
      scrpixel >>= 8;
      rb = ((pixel & 0xFF00FF) * opacity +
          (scrpixel & 0xFF00FF) * transp) >> 8;
      g  = ((pixel & 0x00FF00) * opacity +
          (scrpixel & 0x00FF00) * transp) >> 8;

    return ((rb & 0xFF00FF) | (g & 0xFF00)) << 8; 

}

static inline uint32_t colour_rgba_to_pixel_bgra(nsfb_colour_t c)
{
       
        return (((c & 0xFF00) << 16 ) |
                ((c & 0xFF0000) ) |
                ((c & 0xFF000000) >> 16) );
}
static inline nsfb_colour_t pixel_bgra_to_colour_rgba(uint32_t pixel)
{
    
    //return (pixel >> 8) & ~0xFF000000U;
    
    return (((pixel & 0xFF000000) >> 16  ) |
                ((pixel & 0xFF0000) ) |
                ((pixel & 0xFF00) << 16));
    
} 

#endif



Bye
/*
 * Copyright 2009 Vincent Sanders <[email protected]>
 *
 * This file is part of libnsfb, http://www.netsurf-browser.org/
 * Licenced under the MIT License,
 *                http://www.opensource.org/licenses/mit-license.php
 */

#include <stdbool.h>
#include <endian.h>
#include <stdlib.h>

#include "libnsfb.h"
#include "libnsfb_plot_util.h"

#include "nsfb.h"
#include "nsfb_plot.h"
#include "plotters.h"



static inline uint32_t *
get_xy_loc(nsfb_t *nsfb, int x, int y)
{
        return (uint32_t *)(nsfb->ptr + (y * nsfb->linelen) + (x << 2));
}



#if __BYTE_ORDER == __BIG_ENDIAN
#ifdef __BIG_ENDIAN_BGRA__
static inline nsfb_colour_t pixel_to_colour(uint32_t pixel)
{
        return (pixel >> 8) & ~0xFF000000U;
}

/* convert a colour value to a 32bpp pixel value ready for screen output */
static inline uint32_t colour_to_pixel(nsfb_colour_t c)
{
        return (c << 8);
}



// this funcs are need because bitmaps have diffrent format (rgba)when get from 
netsurf.
//if your SDL surface work in rgba mode(seem in SDL_SWSURFACE done), you need 
diffrent funcs.
static inline nsfb_colour_t nsfb_plot_ablend_rgba(nsfb_colour_t 
pixel,nsfb_colour_t  scrpixel)
{
          int opacity = pixel & 0xFF;
          int transp = 0x100 - opacity;
      uint32_t rb, g; 
          pixel >>= 8;
          scrpixel >>= 8;
          rb = ((pixel & 0xFF00FF) * opacity +
          (scrpixel & 0xFF00FF) * transp) >> 8;
      g  = ((pixel & 0x00FF00) * opacity +
          (scrpixel & 0x00FF00) * transp) >> 8;

    return ((rb & 0xFF00FF) | (g & 0xFF00)) << 8; 

}

static inline uint32_t colour_rgba_to_pixel_bgra(nsfb_colour_t c)
{
           
                return (((c & 0xFF00) << 16 ) |
                ((c & 0xFF0000) ) |
                ((c & 0xFF000000) >> 16) );
}
static inline nsfb_colour_t pixel_bgra_to_colour_rgba(uint32_t pixel)
{
        
    //return (pixel >> 8) & ~0xFF000000U;
        
        return (((pixel & 0xFF000000) >> 16  ) |
                ((pixel & 0xFF0000)) |
                ((pixel & 0xFF00) << 16));
        
} 

#endif

#else /* __BYTE_ORDER == __BIG_ENDIAN */
static inline nsfb_colour_t pixel_to_colour(uint32_t pixel)
{
        return ((pixel & 0xFF) << 16) |
                ((pixel & 0xFF00)) |
                ((pixel & 0xFF0000) >> 16);
}

/* convert a colour value to a 32bpp pixel value ready for screen output */
static inline uint32_t colour_to_pixel(nsfb_colour_t c)
{
        return ((c & 0xff0000) >> 16) | (c & 0xff00) | ((c & 0xff) << 16);
}
#endif

#define SIGN(x)  ((x<0) ?  -1  :  ((x>0) ? 1 : 0))

static bool 
line(nsfb_t *nsfb, 
     nsfb_bbox_t *line, 
     int line_width, 
     nsfb_colour_t c, 
     bool dotted, 
     bool dashed)
{
        int w;
        uint32_t ent;
        uint32_t *pvideo;
        int x, y, i;
        int dx, dy, sdy;
        int dxabs, dyabs;

        line_width = line_width;
        dotted = dotted;
        dashed = dashed;

        ent = colour_to_pixel(c);

        if (line->y0 == line->y1) {
                /* horizontal line special cased */
                if (!nsfb_plot_clip_ctx(nsfb, line))
                        return true; /* line outside clipping */

                pvideo = get_xy_loc(nsfb, line->x0, line->y0);

                w = line->x1 - line->x0;
                while (w-- > 0) 
                        *(pvideo + w) = ent;
                
                return true;
        } else {
                /* standard bresenham line */
                if (!nsfb_plot_clip_line_ctx(nsfb, line))
                        return true; /* line outside clipping */

                /* the horizontal distance of the line */
                dx = line->x1 - line->x0;
                dxabs = abs (dx);

                /* the vertical distance of the line */
                dy = line->y1 - line->y0;
                dyabs = abs (dy);

                sdy = dx ? SIGN(dy) * SIGN(dx) : SIGN(dy);

                if (dx >= 0)
                        pvideo = get_xy_loc(nsfb, line->x0, line->y0);
                else
                        pvideo = get_xy_loc(nsfb, line->x1, line->y1);

                x = dyabs >> 1;
                y = dxabs >> 1;

                if (dxabs >= dyabs) {
                        /* the line is more horizontal than vertical */
                        for (i = 0; i < dxabs; i++) {
                                *pvideo = ent;

                                pvideo++;
                                y += dyabs;
                                if (y >= dxabs) {
                                        y -= dxabs;
                                        pvideo += sdy * (nsfb->linelen>>2);
                                }
                        }
                } else {
                        /* the line is more vertical than horizontal */
                        for (i = 0; i < dyabs; i++) {
                                *pvideo = ent;
                                pvideo += sdy * (nsfb->linelen >> 2);

                                x += dxabs;
                                if (x >= dyabs) {
                                        x -= dyabs;
                                        pvideo++;
                                }
                        }
                }

        }

        return true;
}



static bool fill(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t c)
{
        int w;
        uint32_t *pvid;
        uint32_t ent;
        uint32_t llen;
        uint32_t width;
        uint32_t height;

        if (!nsfb_plot_clip_ctx(nsfb, rect))
                return true; /* fill lies outside current clipping region */

        ent = colour_to_pixel(c);
        width = rect->x1 - rect->x0;
        height = rect->y1 - rect->y0;
        llen = (nsfb->linelen >> 2) - width;

        pvid = get_xy_loc(nsfb, rect->x0, rect->y0);

        while (height-- > 0) {
                w = width;
                while (w >= 16) {
                       *pvid++ = ent; *pvid++ = ent;
                       *pvid++ = ent; *pvid++ = ent;
                       *pvid++ = ent; *pvid++ = ent;
                       *pvid++ = ent; *pvid++ = ent;
                       *pvid++ = ent; *pvid++ = ent;
                       *pvid++ = ent; *pvid++ = ent;
                       *pvid++ = ent; *pvid++ = ent;
                       *pvid++ = ent; *pvid++ = ent;
                       w-=16;
                }
                while (w >= 4) {
                       *pvid++ = ent; *pvid++ = ent;
                       *pvid++ = ent; *pvid++ = ent;
                       w-=4;
                }
                while (w > 0) {
                       *pvid++ = ent;
                       w--;
                }
                pvid += llen;
        }

        return true;
}




static bool point(nsfb_t *nsfb, int x, int y, nsfb_colour_t c)
{
        uint32_t *pvideo;

        /* check point lies within clipping region */
        if ((x < nsfb->clip.x0) || 
            (x >= nsfb->clip.x1) ||
            (y < nsfb->clip.y0) ||
            (y >= nsfb->clip.y1)) 
                return true;

        pvideo = get_xy_loc(nsfb, x, y);

        if ((c & 0xFF000000) != 0) {
                if ((c & 0xFF000000) != 0xFF000000) {
                        c = nsfb_plot_ablend(c, pixel_to_colour(*pvideo));
                }

                *pvideo = colour_to_pixel(c);
        }
        return true;
}

static bool
glyph1(nsfb_t *nsfb,
       nsfb_bbox_t *loc,
       const uint8_t *pixel,
       int pitch,
       nsfb_colour_t c)
{
        uint32_t *pvideo;
        int xloop, yloop;
        int xoff, yoff; /* x and y offset into image */
        int x = loc->x0;
        int y = loc->y0;
        int width = loc->x1 - loc->x0;
        int height = loc->y1 - loc->y0;
        uint32_t fgcol;
        const uint8_t *fntd;
        uint8_t row;

        if (!nsfb_plot_clip_ctx(nsfb, loc))
                return true;

        if (height > (loc->y1 - loc->y0))
                height = (loc->y1 - loc->y0);

        if (width > (loc->x1 - loc->x0))
                width = (loc->x1 - loc->x0);

        xoff = loc->x0 - x;
        yoff = loc->y0 - y;

        pvideo = get_xy_loc(nsfb, loc->x0, loc->y0);

        fgcol = colour_to_pixel(c);

        for (yloop = yoff; yloop < height; yloop++) {
                fntd = pixel + (yloop * (pitch>>3)) + (xoff>>3);
                row = (*fntd++) << (xoff & 3);
                for (xloop = xoff; xloop < width ; xloop++) {
                        if (((xloop % 8) == 0) && (xloop != 0)) {
                                row = *fntd++;
                        }

                        if ((row & 0x80) != 0) {
                                *(pvideo + xloop) = fgcol;
                        }
                        row = row << 1;

                }

                pvideo += (nsfb->linelen >> 2);
        }

        return true;
}

static bool
glyph8(nsfb_t *nsfb,
       nsfb_bbox_t *loc,
       const uint8_t *pixel,
       int pitch,
       nsfb_colour_t c)
{
        uint32_t *pvideo;
        nsfb_colour_t abpixel; /* alphablended pixel */
        int xloop, yloop;
        int xoff, yoff; /* x and y offset into image */
        int x = loc->x0;
        int y = loc->y0;
        int width = loc->x1 - loc->x0;
        int height = loc->y1 - loc->y0;
        uint32_t fgcol;

        if (!nsfb_plot_clip_ctx(nsfb, loc))
                return true;

        if (height > (loc->y1 - loc->y0))
                height = (loc->y1 - loc->y0);

        if (width > (loc->x1 - loc->x0))
                width = (loc->x1 - loc->x0);

        xoff = loc->x0 - x;
        yoff = loc->y0 - y;

        pvideo = get_xy_loc(nsfb, loc->x0, loc->y0);

        fgcol = c & 0xFFFFFF;

        for (yloop = 0; yloop < height; yloop++) {
                for (xloop = 0; xloop < width; xloop++) {
                        abpixel = (pixel[((yoff + yloop) * pitch) + xloop + 
xoff] << 24) | fgcol;
                        if ((abpixel & 0xFF000000) != 0) {
                                /* pixel is not transparent */
                                if ((abpixel & 0xFF000000) != 0xFF000000) {
                                        abpixel = nsfb_plot_ablend(abpixel,
                                                                   
pixel_to_colour(*(pvideo + xloop)));
                                }

                                *(pvideo + xloop) = colour_to_pixel(abpixel); 
                        }
                }
                pvideo += (nsfb->linelen >> 2);
        }

        return true;
}

static bool 
bitmap(nsfb_t *nsfb,
       const nsfb_bbox_t *loc,
       const nsfb_colour_t *pixel, 
       int bmp_width, 
       int bmp_height, 
       int bmp_stride,
       bool alpha)
{
        uint32_t *pvideo;
        nsfb_colour_t abpixel = 0; /* alphablended pixel */
        int xloop, yloop;
        int xoff, yoff; /* x and y offset into image */
        int x = loc->x0;
        int y = loc->y0;
        int width = loc->x1 - loc->x0;
        int height = loc->y1 - loc->y0;
        nsfb_bbox_t clipped; /* clipped display */

        /* TODO here we should scale the image from bmp_width to width, for
         * now simply crop.
         */
        if (width > bmp_width)
                width = bmp_width;

        if (height > bmp_height)
                height = bmp_height;

        /* The part of the scaled image actually displayed is cropped to the
         * current context.
         */
        clipped.x0 = x;
        clipped.y0 = y;
        clipped.x1 = x + width;
        clipped.y1 = y + height;

        if (!nsfb_plot_clip_ctx(nsfb, &clipped)) {
                return true;
        }

        if (height > (clipped.y1 - clipped.y0))
                height = (clipped.y1 - clipped.y0);

        if (width > (clipped.x1 - clipped.x0))
                width = (clipped.x1 - clipped.x0);

        xoff = clipped.x0 - x;
        yoff = (clipped.y0 - y) * bmp_width;
        height = height * bmp_stride + yoff;
 
        /* plot the image */
        pvideo = get_xy_loc(nsfb, clipped.x0, clipped.y0);

        if (alpha) {
                for (yloop = yoff; yloop < height; yloop += bmp_stride) {
                        for (xloop = 0; xloop < width; xloop++) {
                                abpixel = pixel[yloop + xloop + xoff];
#ifdef __BIG_ENDIAN_BGRA__                                                      
        
                                if ((abpixel & 0x000000FF) != 0) {
                                        if ((abpixel & 0x000000FF) != 
0x000000FF) {
                                                abpixel = 
nsfb_plot_ablend_rgba(abpixel,
                                                                           
pixel_bgra_to_colour_rgba(*(pvideo + xloop)));
                                        }
                                                                                
*(pvideo + xloop) = colour_rgba_to_pixel_bgra(abpixel);
#else
                                if ((abpixel & 0xFF000000) != 0) {
                                        if ((abpixel & 0xFF000000) != 
0xFF000000) {
                                                abpixel = 
nsfb_plot_ablend(abpixel,
                                                                           
pixel_to_colour(*(pvideo + xloop)));
                                        }
                                        *(pvideo + xloop) = 
colour_to_pixel(abpixel);
#endif
                                }
                        }
                        pvideo += (nsfb->linelen >> 2);
                }
        } else {
                for (yloop = yoff; yloop < height; yloop += bmp_stride) {
                        for (xloop = 0; xloop < width; xloop++) {
                                abpixel = pixel[yloop + xloop + xoff];
#ifdef __BIG_ENDIAN_BGRA__                                                      
        
                                *(pvideo + xloop) = 
colour_rgba_to_pixel_bgra(abpixel);
#else
                                *(pvideo + xloop) = colour_to_pixel(abpixel);
#endif
                        }
                        pvideo += (nsfb->linelen >> 2);
                }
        }
        return true;
}

static bool readrect(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t *buffer)
{
        uint32_t *pvideo;
        int xloop, yloop;
        int width; 

        if (!nsfb_plot_clip_ctx(nsfb, rect)) {
                return true;
        }

        width = rect->x1 - rect->x0;

        pvideo = get_xy_loc(nsfb, rect->x0, rect->y0);

        for (yloop = rect->y0; yloop < rect->y1; yloop += 1) {
                for (xloop = 0; xloop < width; xloop++) {
#ifdef __BIG_ENDIAN_BGRA__                                         
                        *buffer = pixel_bgra_to_colour_rgba(*(pvideo + xloop));
#else
                        *buffer = pixel_to_colour(*(pvideo + xloop));
#endif
                        buffer++;
                }
                pvideo += (nsfb->linelen >> 2);
        }
        return true;
}

const nsfb_plotter_fns_t _nsfb_32bpp_plotters = {
        .line = line,
        .fill = fill,
        .point = point,
        .bitmap = bitmap,
        .glyph8 = glyph8,
        .glyph1 = glyph1,
        .readrect = readrect,
};

/*
 * Local Variables:
 * c-basic-offset:8
 * End:
 */

Reply via email to