/* * Copyright (c) 2009-2023 Julien Nadeau Carriere * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Test if a given mode and bits/pixel combination is supported. */ #ifdef AG_INLINE_HEADER static __inline__ int _Const_Attribute AG_PixelFormatIsSupported(AG_SurfaceMode mode, int BitsPerPixel) #else int ag_pixel_format_is_supported(AG_SurfaceMode mode, int BitsPerPixel) #endif { switch (mode) { case AG_SURFACE_PACKED: switch (BitsPerPixel) { case 32: case 24: #if AG_MODEL == AG_LARGE case 64: case 48: case 40: #endif case 16: return (1); } break; case AG_SURFACE_INDEXED: switch (BitsPerPixel) { case 8: case 4: case 2: case 1: return (1); } break; case AG_SURFACE_GRAYSCALE: switch (BitsPerPixel) { case 16: case 32: #if AG_MODEL == AG_LARGE case 64: #endif return (1); } break; default: break; } return (0); } /* * Test whether two pixel formats are identical. * In indexed mode, include both palettes in the comparison. */ #ifdef AG_INLINE_HEADER static __inline__ int _Pure_Attribute AG_PixelFormatCompare(const AG_PixelFormat *_Nonnull a, const AG_PixelFormat *_Nonnull b) #else int ag_pixel_format_compare(const AG_PixelFormat *a, const AG_PixelFormat *b) #endif { if (a->mode != b->mode || a->BitsPerPixel != b->BitsPerPixel) { return (1); } switch (a->mode) { case AG_SURFACE_PACKED: return !(a->Rmask == b->Rmask && a->Gmask == b->Gmask && a->Bmask == b->Bmask && a->Amask == b->Amask); case AG_SURFACE_INDEXED: #ifdef AG_DEBUG if (a->palette->nColors != b->palette->nColors) { AG_SetError("nColors %u != %u", a->palette->nColors, b->palette->nColors); AG_FatalError(NULL); } #endif return memcmp(a->palette->colors, b->palette->colors, a->palette->nColors * sizeof(AG_Color)); default: case AG_SURFACE_GRAYSCALE: return (0); } } /* Test if x,y lies inside surface's clipping rectangle */ #ifdef AG_INLINE_HEADER static __inline__ int _Pure_Attribute AG_SurfaceClipped(const AG_Surface *_Nonnull S, int x, int y) #else int ag_surface_clipped(const AG_Surface *S, int x, int y) #endif { return (x < S->clipRect.x || x >= S->clipRect.x + S->clipRect.w || y < S->clipRect.y || y >= S->clipRect.y + S->clipRect.h); } /* * Map an AG_Color to a 32-bit wide pixel value. * If the pixel format is >32-bit then return a 32-bit approximation. */ #ifdef AG_INLINE_HEADER static __inline__ Uint32 _Pure_Attribute AG_MapPixel32(const AG_PixelFormat *_Nonnull pf, const AG_Color *_Nonnull c) #else Uint32 ag_map_pixel32(const AG_PixelFormat *pf, const AG_Color *c) #endif { #if AG_MODEL == AG_LARGE return AG_MapPixel32_RGBA16(pf, c->r, c->g, c->b, c->a); #else return AG_MapPixel32_RGBA8(pf, c->r, c->g, c->b, c->a); #endif } #if AG_MODEL == AG_LARGE # define AG_EXTRACT_COMPONENT16(rv, mask, shift, loss) \ tmp = (px & mask) >> shift; \ (rv) = (tmp << loss) | (tmp >> (16 - (loss << 1))) /* * Map 16bpc RGB components to a 64-bit (1- to 64-bpp) pixel. */ # ifdef AG_INLINE_HEADER static __inline__ Uint64 _Pure_Attribute AG_MapPixel64_RGB16(const AG_PixelFormat *_Nonnull pf, Uint16 r, Uint16 g, Uint16 b) # else Uint64 ag_map_pixel64_rgb16(const AG_PixelFormat *pf, Uint16 r, Uint16 g, Uint16 b) # endif { switch (pf->mode) { case AG_SURFACE_PACKED: default: return ((Uint64)r >> pf->Rloss) << pf->Rshift | ((Uint64)g >> pf->Gloss) << pf->Gshift | ((Uint64)b >> pf->Bloss) << pf->Bshift | ((AG_OPAQUE >> pf->Aloss) << pf->Ashift & pf->Amask); case AG_SURFACE_INDEXED: return AG_MapPixelIndexed(pf, r,g,b, AG_OPAQUE); case AG_SURFACE_GRAYSCALE: return AG_MapPixelGrayscale(pf, r,g,b, AG_OPAQUE); } } /* * Map 16bpc RGBA components to a 64-bit (1- to 64-bpp) pixel. */ # ifdef AG_INLINE_HEADER static __inline__ Uint64 _Pure_Attribute AG_MapPixel64_RGBA16(const AG_PixelFormat *_Nonnull pf, Uint16 r, Uint16 g, Uint16 b, Uint16 a) # else Uint64 ag_map_pixel64_rgba16(const AG_PixelFormat *pf, Uint16 r, Uint16 g, Uint16 b, Uint16 a) # endif { switch (pf->mode) { case AG_SURFACE_PACKED: default: return ((Uint64)r >> pf->Rloss) << pf->Rshift | ((Uint64)g >> pf->Gloss) << pf->Gshift | ((Uint64)b >> pf->Bloss) << pf->Bshift | (((Uint64)a >> pf->Aloss) << pf->Ashift & pf->Amask); case AG_SURFACE_INDEXED: return AG_MapPixelIndexed(pf, r,g,b,a); case AG_SURFACE_GRAYSCALE: return AG_MapPixelGrayscale(pf, r,g,b,a); } } /* * Map an AG_Color to a 64-bit (1- to 64-bpp) pixel. */ # ifdef AG_INLINE_HEADER static __inline__ Uint64 _Pure_Attribute AG_MapPixel64(const AG_PixelFormat *_Nonnull pf, const AG_Color *_Nonnull c) # else Uint64 ag_map_pixel64(const AG_PixelFormat *pf, const AG_Color *c) # endif { return AG_MapPixel64_RGBA16(pf, c->r, c->g, c->b, c->a); } /* * Extract 16-bit RGB components from a 64-bit (1- to 64-bpp) pixel. */ # ifdef AG_INLINE_HEADER static __inline__ void AG_GetColor64_RGB16(Uint64 px, const AG_PixelFormat *_Nonnull pf, Uint16 *_Nonnull r, Uint16 *_Nonnull g, Uint16 *_Nonnull b) # else void ag_get_color64_rgb16(Uint64 px, const AG_PixelFormat *pf, Uint16 *r, Uint16 *g, Uint16 *b) # endif { if (pf->mode == AG_SURFACE_PACKED) { Uint64 tmp; AG_EXTRACT_COMPONENT16(*r, pf->Rmask, pf->Rshift, pf->Rloss); AG_EXTRACT_COMPONENT16(*g, pf->Gmask, pf->Gshift, pf->Gloss); AG_EXTRACT_COMPONENT16(*b, pf->Bmask, pf->Bshift, pf->Bloss); } else if (pf->mode == AG_SURFACE_INDEXED) { const AG_Color *c = &pf->palette->colors[px % pf->palette->nColors]; *r = c->r; *g = c->g; *b = c->b; } else if (pf->mode == AG_SURFACE_GRAYSCALE) { Uint16 dummy; AG_GetColor64_Gray16(px, r,g,b, &dummy); } } /* * Extract 16bpc RGBA components from a 64-bit (1- to 64-bpp) pixel. */ # ifdef AG_INLINE_HEADER static __inline__ void AG_GetColor64_RGBA16(Uint64 px, const AG_PixelFormat *_Nonnull pf, Uint16 *_Nonnull r, Uint16 *_Nonnull g, Uint16 *_Nonnull b, Uint16 *_Nonnull a) # else void ag_get_color64_rgba16(Uint64 px, const AG_PixelFormat *pf, Uint16 *r, Uint16 *g, Uint16 *b, Uint16 *a) # endif { if (pf->mode == AG_SURFACE_PACKED) { Uint64 tmp; AG_EXTRACT_COMPONENT16(*r, pf->Rmask, pf->Rshift, pf->Rloss); AG_EXTRACT_COMPONENT16(*g, pf->Gmask, pf->Gshift, pf->Gloss); AG_EXTRACT_COMPONENT16(*b, pf->Bmask, pf->Bshift, pf->Bloss); AG_EXTRACT_COMPONENT16(*a, pf->Amask, pf->Ashift, pf->Aloss); } else if (pf->mode == AG_SURFACE_INDEXED) { const AG_Color *c = &pf->palette->colors[px % pf->palette->nColors]; *r = c->r; *g = c->g; *b = c->b; *a = c->a; } else if (pf->mode == AG_SURFACE_GRAYSCALE) { AG_GetColor64_Gray16(px, r,g,b,a); } } /* * Extract compressed 8-bit RGB components from a 64-bit (1- to 64-bpp) pixel. */ # ifdef AG_INLINE_HEADER static __inline__ void AG_GetColor64_RGB8(Uint64 px, const AG_PixelFormat *_Nonnull pf, Uint8 *_Nonnull r, Uint8 *_Nonnull g, Uint8 *_Nonnull b) # else void ag_get_color64_rgb8(Uint64 px, const AG_PixelFormat *pf, Uint8 *r, Uint8 *g, Uint8 *b) # endif { Uint16 r16, g16, b16; AG_GetColor64_RGB16(px, pf, &r16, &g16, &b16); *r = AG_16to8(r16); *g = AG_16to8(g16); *b = AG_16to8(b16); } /* * Extract compressed 8bpc RGBA components from a 64-bit (1- to 64-bpp) pixel. */ # ifdef AG_INLINE_HEADER static __inline__ void AG_GetColor64_RGBA8(Uint64 px, const AG_PixelFormat *_Nonnull pf, Uint8 *_Nonnull r, Uint8 *_Nonnull g, Uint8 *_Nonnull b, Uint8 *_Nonnull a) # else void ag_get_color64_rgba8(Uint64 px, const AG_PixelFormat *pf, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) # endif { Uint16 r16, g16, b16, a16; AG_GetColor64_RGBA16(px, pf, &r16, &g16, &b16, &a16); *r = AG_16to8(r16); *g = AG_16to8(g16); *b = AG_16to8(b16); *a = AG_16to8(a16); } # undef AG_EXTRACT_COMPONENT16 #endif /* AG_LARGE */ /* * Return the (1- to 64-bit) pixel at coordinates x,y in surface S. * If S is > 32-bit, return a compressed 32-bit approximation. */ #ifdef AG_INLINE_HEADER static __inline__ Uint32 _Pure_Attribute AG_SurfaceGet32(const AG_Surface *_Nonnull S, int x, int y) #else Uint32 ag_surface_get32(const AG_Surface *S, int x, int y) #endif { #ifdef DEBUG_SURFACE_GET if (x < 0 || y < 0 || x >= S->w || y >= S->h) AG_FatalErrorF("Illegal AG_SurfaceGet32() access (%d,%d in %ux%u)", x,y, S->w, S->h); #endif if (S->format.BitsPerPixel < 8) { return (Uint32)AG_SurfaceGet8(S, x,y); } else { return AG_SurfaceGet32_At(S, S->pixels + y*S->pitch + S->Lpadding + x*S->format.BytesPerPixel); } } /* * Return the (8- to 64-bit) pixel at address p in surface S. * If S is > 32-bit, return a compressed 32-bit approximation. */ #ifdef AG_INLINE_HEADER static __inline__ Uint32 _Pure_Attribute AG_SurfaceGet32_At(const AG_Surface *_Nonnull S, const Uint8 *_Nonnull p) #else Uint32 ag_surface_get32_at(const AG_Surface *S, const Uint8 *p) #endif { switch (S->format.BitsPerPixel) { case 32: return (*(Uint32 *)p); case 24: #if AG_BYTEORDER == AG_BIG_ENDIAN return ((p[0] << 16) | (p[1] << 8) | p[2]); #else return (p[0] | (p[1] << 8) | (p[2] << 16)); #endif #if AG_MODEL == AG_LARGE case 64: { AG_Color c; AG_GetColor64(&c, *(Uint64 *)p, &S->format); return AG_MapPixel32(&S->format, &c); } break; case 48: { Uint64 px; AG_Color c; # if AG_BYTEORDER == AG_BIG_ENDIAN px = ((Uint64)p[0] << 40) | ((Uint64)p[1] << 32) | ((Uint64)p[2] << 24) | ((Uint64)p[3] << 16) | ((Uint64)p[4] << 8) | (Uint64)p[5]; # else px = (Uint64)p[0] | ((Uint64)p[1] << 8) | ((Uint64)p[2] << 16) | ((Uint64)p[3] << 24) | ((Uint64)p[4] << 32) | ((Uint64)p[5] << 40); # endif AG_GetColor64(&c, px, &S->format); return AG_MapPixel32(&S->format, &c); } case 40: { Uint64 px; AG_Color c; # if AG_BYTEORDER == AG_BIG_ENDIAN px = (((Uint64)p[0] << 32) | ((Uint64)p[1] << 24) | ((Uint64)p[2] << 16) | ((Uint64)p[3] << 8) | (Uint64)p[4]; # else px = (Uint64)p[0] | ((Uint64)p[1] << 8) | ((Uint64)p[2] << 16) | ((Uint64)p[3] << 24) | ((Uint64)p[4] << 32); # endif AG_GetColor64(&c, px, &S->format); return AG_MapPixel32(&S->format, &c); } #endif /* AG_LARGE */ case 16: return (*(Uint16 *)p); default: break; } return (*p); } #if AG_MODEL == AG_LARGE /* * Return the (1- to 64-bit) pixel at coordinates x,y in surface S. */ # ifdef AG_INLINE_HEADER static __inline__ Uint64 _Pure_Attribute AG_SurfaceGet64(const AG_Surface *_Nonnull S, int x, int y) # else Uint64 ag_surface_get64(const AG_Surface *S, int x, int y) # endif { # ifdef DEBUG_SURFACE_GET if (x < 0 || y < 0 || x >= S->w || y >= S->h) AG_FatalErrorF("Illegal AG_SurfaceGet64() access " "(%d,%d in %ux%u)", x, y, S->w, S->h); # endif if (S->format.BitsPerPixel < 8) { return (Uint64)AG_SurfaceGet8(S, x,y); } else { return AG_SurfaceGet64_At(S, S->pixels + y*S->pitch + S->Lpadding + x*S->format.BytesPerPixel); } } /* * Return the (8- to 64-bit) pixel at address p in surface S. */ # ifdef AG_INLINE_HEADER static __inline__ Uint64 _Pure_Attribute AG_SurfaceGet64_At(const AG_Surface *_Nonnull S, const Uint8 *_Nonnull p) # else Uint64 ag_surface_get64_at(const AG_Surface *S, const Uint8 *p) # endif { switch (S->format.BitsPerPixel) { case 32: return (*(Uint32 *)p); case 24: # if AG_BYTEORDER == AG_BIG_ENDIAN return ((p[0] << 16) | (p[1] << 8) | p[2]); # else return (p[0] | (p[1] << 8) | (p[2] << 16)); # endif case 64: return (*(Uint64 *)p); case 40: # if AG_BYTEORDER == AG_BIG_ENDIAN return ((Uint64)p[0] << 32) | ((Uint64)p[1] << 24) | ((Uint64)p[2] << 16) | ((Uint64)p[3] << 8) | (Uint64)p[4]; # else return (Uint64)p[0] | ((Uint64)p[1] << 8) | ((Uint64)p[2] << 16) | ((Uint64)p[3] << 24) | ((Uint64)p[4] << 32); # endif case 48: # if AG_BYTEORDER == AG_BIG_ENDIAN return ((Uint64)p[0] << 40) | ((Uint64)p[1] << 32) | ((Uint64)p[2] << 24) | ((Uint64)p[3] << 16) | ((Uint64)p[4] << 8) | (Uint64)p[5]; # else return (Uint64)p[0] | ((Uint64)p[1] << 8) | ((Uint64)p[2] << 16) | ((Uint64)p[3] << 24) | ((Uint64)p[4] << 32) | ((Uint64)p[5] << 40); # endif case 16: return (*(Uint16 *)p); default: break; } return (*p); } #endif /* AG_LARGE */ /* * Write to the (1- to 64-bit) pixel at coordinates x,y in surface S. */ #ifdef AG_INLINE_HEADER static __inline__ void AG_SurfacePut32(AG_Surface *_Nonnull S, int x, int y, Uint32 px) #else void ag_surface_put32(AG_Surface *S, int x, int y, Uint32 px) #endif { if (S->format.BitsPerPixel < 8) { AG_SurfacePut8(S, x,y, (Uint8)px); } else { AG_SurfacePut32_At(S, S->pixels + y*S->pitch + S->Lpadding + x*S->format.BytesPerPixel, px); } } /* * Write to the (8- to 64-bit) pixel at address p in surface S. */ #ifdef AG_INLINE_HEADER static __inline__ void AG_SurfacePut32_At(AG_Surface *_Nonnull S, Uint8 *_Nonnull p, Uint32 px) #else void ag_surface_put32_at(AG_Surface *S, Uint8 *p, Uint32 px) #endif { switch (S->format.BitsPerPixel) { case 32: *(Uint32 *)p = px; break; case 24: #if AG_BYTEORDER == AG_BIG_ENDIAN p[0] = (px >> 16) & 0xff; p[1] = (px >> 8) & 0xff; p[2] = (px) & 0xff; #else p[0] = (px) & 0xff; p[1] = (px >> 8) & 0xff; p[2] = (px >> 16) & 0xff; #endif break; #if AG_MODEL == AG_LARGE case 64: { AG_Color c; AG_GetColor32(&c, px, &S->format); *(Uint64 *)p = AG_MapPixel64(&S->format, &c); break; } case 48: { AG_Color c; Uint64 px64; AG_GetColor32(&c, px, &S->format); px64 = AG_MapPixel64(&S->format, &c); # if AG_BYTEORDER == AG_BIG_ENDIAN p[0] = (px64 >> 40) & 0xff; p[1] = (px64 >> 32) & 0xff; p[2] = (px64 >> 24) & 0xff; p[3] = (px64 >> 16) & 0xff; p[4] = (px64 >> 8) & 0xff; p[5] = (px64) & 0xff; # else p[0] = (px64) & 0xff; p[1] = (px64 >> 8) & 0xff; p[2] = (px64 >> 16) & 0xff; p[3] = (px64 >> 24) & 0xff; p[4] = (px64 >> 32) & 0xff; p[5] = (px64 >> 40) & 0xff; # endif break; } case 40: { AG_Color c; Uint64 px64; AG_GetColor32(&c, px, &S->format); px64 = AG_MapPixel64(&S->format, &c); # if AG_BYTEORDER == AG_BIG_ENDIAN p[0] = (px64 >> 32) & 0xff; p[1] = (px64 >> 24) & 0xff; p[2] = (px64 >> 16) & 0xff; p[3] = (px64 >> 8) & 0xff; p[4] = (px64) & 0xff; # else p[0] = (px64) & 0xff; p[1] = (px64 >> 8) & 0xff; p[2] = (px64 >> 16) & 0xff; p[3] = (px64 >> 24) & 0xff; p[4] = (px64 >> 32) & 0xff; # endif break; } #endif /* AG_LARGE */ case 16: *(Uint16 *)p = (Uint16)px; break; default: *p = (Uint8)px; break; } } #if AG_MODEL == AG_LARGE /* * Write the pixel at x,y in a (1- to 64-bit) surface S. */ # ifdef AG_INLINE_HEADER static __inline__ void AG_SurfacePut64(AG_Surface *_Nonnull S, int x, int y, Uint64 px) # else void ag_surface_put64(AG_Surface *S, int x, int y, Uint64 px) # endif { if (S->format.BitsPerPixel < 8) { AG_SurfacePut8(S, x,y, (Uint8)px); } else { AG_SurfacePut64_At(S, S->pixels + y*S->pitch + S->Lpadding + x*S->format.BytesPerPixel, px); } } /* * Write the pixel at address p in an (8- to 64-bpp) surface S. */ # ifdef AG_INLINE_HEADER static __inline__ void AG_SurfacePut64_At(AG_Surface *_Nonnull S, Uint8 *_Nonnull p, Uint64 px) # else void ag_surface_put64_at(AG_Surface *S, Uint8 *p, Uint64 px) # endif { switch (S->format.BitsPerPixel) { case 32: *(Uint32 *)p = px; break; case 64: *(Uint64 *)p = px; break; case 24: #if AG_BYTEORDER == AG_BIG_ENDIAN p[0] = (px >> 16) & 0xff; p[1] = (px >> 8) & 0xff; p[2] = (px) & 0xff; #else p[0] = (px) & 0xff; p[1] = (px >> 8) & 0xff; p[2] = (px >> 16) & 0xff; #endif break; case 48: #if AG_BYTEORDER == AG_BIG_ENDIAN p[0] = (px >> 40) & 0xff; p[1] = (px >> 32) & 0xff; p[2] = (px >> 24) & 0xff; p[3] = (px >> 16) & 0xff; p[4] = (px >> 8) & 0xff; p[5] = (px) & 0xff; #else p[0] = (px) & 0xff; p[1] = (px >> 8) & 0xff; p[2] = (px >> 16) & 0xff; p[3] = (px >> 24) & 0xff; p[4] = (px >> 32) & 0xff; p[5] = (px >> 40) & 0xff; #endif break; case 40: #if AG_BYTEORDER == AG_BIG_ENDIAN p[0] = (px >> 32) & 0xff; p[1] = (px >> 24) & 0xff; p[2] = (px >> 16) & 0xff; p[3] = (px >> 8) & 0xff; p[4] = (px) & 0xff; #else p[0] = (px) & 0xff; p[1] = (px >> 8) & 0xff; p[2] = (px >> 16) & 0xff; p[3] = (px >> 24) & 0xff; p[4] = (px >> 32) & 0xff; #endif break; case 16: *(Uint16 *)p = (Uint16)px; break; case 8: default: *p = (Uint8)px; break; } } /* * Blend 16bpc RGBA components with the pixel at x,y and overwrite it with * the result. No clipping is done. */ # ifdef AG_INLINE_HEADER static __inline__ void AG_SurfaceBlendRGB16(AG_Surface *_Nonnull S, int x, int y, Uint16 r, Uint16 g, Uint16 b, Uint16 a) # else void ag_surface_blend_rgb16(AG_Surface *S, int x, int y, Uint16 r, Uint16 g, Uint16 b, Uint16 a) # endif { AG_Color c = { r,g,b,a }; AG_SurfaceBlend_At(S, S->pixels + y * S->pitch + S->Lpadding + x * S->format.BytesPerPixel, &c); } /* * Blend 16bpc RGBA components with the pixel at address p and overwrite it * with the result. No clipping is done. */ # ifdef AG_INLINE_HEADER static __inline__ void AG_SurfaceBlendRGB16_At(AG_Surface *_Nonnull S, Uint8 *_Nonnull p, Uint16 r, Uint16 g, Uint16 b, Uint16 a) # else void ag_surface_blend_rgb16_at(AG_Surface *S, Uint8 *p, Uint16 r, Uint16 g, Uint16 b, Uint16 a) # endif { AG_Color c = { r,g,b,a }; AG_SurfaceBlend_At(S,p, &c); } #endif /* AG_LARGE */ /* * Blend a color c with the pixel at x,y and overwrite it with the result. * No clipping is done. */ #ifdef AG_INLINE_HEADER static __inline__ void AG_SurfaceBlend(AG_Surface *_Nonnull S, int x, int y, const AG_Color *_Nonnull c) #else void ag_surface_blend(AG_Surface *S, int x, int y, const AG_Color *c) #endif { AG_SurfaceBlend_At(S, S->pixels + y * S->pitch + S->Lpadding + x * S->format.BytesPerPixel, c); } /* * Blend a color c with the pixel at address p and overwrite it with the result. * No clipping is done. */ #ifdef AG_INLINE_HEADER static __inline__ void AG_SurfaceBlend_At(AG_Surface *_Nonnull S, Uint8 *_Nonnull p, const AG_Color *_Nonnull c) #else void ag_surface_blend_at(AG_Surface *S, Uint8 *p, const AG_Color *_Nonnull c) #endif { AG_Color pc; AG_Pixel px; AG_Component ca; px = AG_SurfaceGet_At(S,p); AG_GetColor(&pc, px, &S->format); ca = c->a; pc.a = ((pc.a + ca) > AG_COLOR_LAST) ? AG_COLOR_LAST : (pc.a + ca); AG_SurfacePut_At(S, p, AG_MapPixel_RGBA(&S->format, pc.r + (((c->r - pc.r) * ca) >> AG_COMPONENT_BITS), pc.g + (((c->g - pc.g) * ca) >> AG_COMPONENT_BITS), pc.b + (((c->b - pc.b) * ca) >> AG_COMPONENT_BITS), pc.a)); } /* Release all resources possibly allocated by an AG_PixelFormat. */ #ifdef AG_INLINE_HEADER static __inline__ void AG_PixelFormatFree(AG_PixelFormat *_Nonnull pf) #else void ag_pixel_format_free(AG_PixelFormat *pf) #endif { if (pf->mode == AG_SURFACE_INDEXED) { AG_Free(pf->palette->colors); AG_Free(pf->palette); } } /* Set the per-surface alpha value. */ #ifdef AG_INLINE_HEADER static __inline__ void AG_SurfaceSetAlpha(AG_Surface *_Nonnull S, Uint flags, AG_Component alpha) #else void ag_surface_set_alpha(AG_Surface *S, Uint flags, AG_Component alpha) #endif { S->alpha = alpha; } /* Set the source colorkey flag and per-surface colorkey. */ #ifdef AG_INLINE_HEADER static __inline__ void AG_SurfaceSetColorKey(AG_Surface *_Nonnull S, Uint flags, AG_Pixel colorkey) #else void ag_surface_set_colorkey(AG_Surface *S, Uint flags, AG_Pixel colorkey) #endif { if (flags & AG_SURFACE_COLORKEY) { S->flags |= AG_SURFACE_COLORKEY; } else { S->flags &= ~(AG_SURFACE_COLORKEY); } S->colorkey = colorkey; }