/* * Copyright (c) 2005-2019 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. */ /* * Serialization functions for uncompressed graphic surfaces. */ #include #include #include #include #include const AG_Version agSurfaceVer = { 1, 0 }; void AG_WritePalette(AG_DataSource *ds, const AG_Palette *pal) { int i; AG_WriteUint16(ds, pal->nColors); for (i = 0; i < pal->nColors; i++) AG_WriteColor(ds, &pal->colors[i]); } int AG_ReadPalette(AG_Palette *pal, AG_DataSource *ds) { Uint16 nColors; int i; if ((nColors = AG_ReadUint16(ds)) != pal->nColors) { AG_SetErrorS("Bad color count"); return (-1); } for (i = 0; i < pal->nColors; i++) { AG_ReadColor(&pal->colors[i], ds); } return (0); } void AG_WriteSurface(AG_DataSource *ds, AG_Surface *s) { const AG_PixelFormat *pf = &s->format; AG_WriteVersion(ds, "AG_Surface", &agSurfaceVer); AG_WriteUint16(ds, s->flags & AG_SAVED_SURFACE_FLAGS); AG_WriteUint16(ds, s->w); AG_WriteUint16(ds, s->h); AG_WriteUint8(ds, pf->mode); AG_WriteUint8(ds, pf->BitsPerPixel); switch (pf->mode) { case AG_SURFACE_PACKED: #if AG_MODEL == AG_LARGE if (pf->Rmask > 0xffffffff || pf->Gmask > 0xffffffff || pf->Bmask > 0xffffffff || pf->Amask > 0xffffffff) { AG_WriteUint8(ds, 64); AG_WriteUint64(ds, pf->Rmask); AG_WriteUint64(ds, pf->Gmask); AG_WriteUint64(ds, pf->Bmask); AG_WriteUint64(ds, pf->Amask); } else #else /* !LARGE */ { AG_WriteUint8(ds, 32); AG_WriteUint32(ds, pf->Rmask); AG_WriteUint32(ds, pf->Gmask); AG_WriteUint32(ds, pf->Bmask); AG_WriteUint32(ds, pf->Amask); } #endif break; case AG_SURFACE_INDEXED: AG_WritePalette(ds, pf->palette); break; case AG_SURFACE_GRAYSCALE: AG_WriteUint8(ds, pf->graymode); break; default: break; } AG_WriteRect(ds, &s->clipRect); #if AG_MODEL == AG_LARGE if (s->colorkey > 0xffffffff) { AG_WriteUint8(ds, 64); AG_WriteUint64(ds, s->colorkey); } else #endif { AG_WriteUint8(ds, 32); AG_WriteUint32(ds, s->colorkey); } #if AG_MODEL == AG_LARGE if (s->alpha > 0xff) { AG_WriteUint8(ds, 16); AG_WriteUint16(ds, s->alpha); } else #endif { AG_WriteUint8(ds, 8); AG_WriteUint8(ds, s->alpha); } AG_WriteUint16(ds, s->pitch); AG_Write(ds, s->pixels, (s->pitch * s->h)); /* TODO serialize animation frames */ AG_WriteUint32(ds, 0); /* s->n */ } AG_Surface * AG_ReadSurface(AG_DataSource *ds) { AG_PixelFormat pf; AG_Surface *s; AG_SurfaceMode mode; Uint w,h, flags; int BitsPerPixel; Uint8 size; if (AG_ReadVersion(ds, "AG_Surface", &agSurfaceVer, NULL) != 0) { return (NULL); } flags = (AG_ReadUint16(ds) & AG_SAVED_SURFACE_FLAGS); w = AG_ReadUint16(ds); h = AG_ReadUint16(ds); mode = pf.mode = (AG_SurfaceMode)AG_ReadUint8(ds); BitsPerPixel = AG_ReadUint8(ds); if (!AG_PixelFormatIsSupported(mode, BitsPerPixel)) { AG_SetErrorS("Bad mode/bpp combination"); return (NULL); } switch (pf.mode) { case AG_SURFACE_PACKED: if ((size = AG_ReadUint8(ds)) == 64) { #if AG_MODEL == AG_LARGE Uint64 Rmask = AG_ReadUint64(ds); Uint64 Gmask = AG_ReadUint64(ds); Uint64 Bmask = AG_ReadUint64(ds); Uint64 Amask = AG_ReadUint64(ds); AG_PixelFormatRGBA(&pf, BitsPerPixel, Rmask, Gmask, Bmask, Amask); #else AG_SetErrorS("64bpp surfaces require AG_LARGE"); return (NULL); #endif } else if (size == 32) { Uint32 Rmask = AG_ReadUint32(ds); Uint32 Gmask = AG_ReadUint32(ds); Uint32 Bmask = AG_ReadUint32(ds); Uint32 Amask = AG_ReadUint32(ds); AG_PixelFormatRGBA(&pf, BitsPerPixel, Rmask, Gmask, Bmask, Amask); } else { AG_SetErrorS("Bad mask size"); return (NULL); } break; case AG_SURFACE_INDEXED: AG_PixelFormatIndexed(&pf, BitsPerPixel); if (AG_ReadPalette(pf.palette, ds) == -1) { return (NULL); } break; case AG_SURFACE_GRAYSCALE: AG_PixelFormatGrayscale(&pf, BitsPerPixel); pf.graymode = AG_ReadUint8(ds); break; default: break; } if ((s = AG_SurfaceNew(&pf, w,h, flags)) == NULL) { return (NULL); } AG_ReadRect(&s->clipRect, ds); if ((size = AG_ReadUint8(ds)) == 64) { #if AG_MODEL == AG_LARGE s->colorkey = AG_ReadUint64(ds); #else AG_SetErrorS("64bpp colorkey needs AG_LARGE"); goto fail; #endif } else if (size == 32) { s->colorkey = AG_ReadUint32(ds); } else { AG_SetErrorS("Bad colorkey size"); goto fail; } if ((size = AG_ReadUint8(ds)) == 16) { #if AG_MODEL == AG_LARGE s->alpha = AG_ReadUint16(ds); #else s->alpha = AG_16to8(AG_ReadUint16(ds)); #endif } else if (size == 8) { #if AG_MODEL == AG_LARGE s->alpha = AG_8to16(AG_ReadUint8(ds)); #else s->alpha = AG_ReadUint8(ds); #endif } else { AG_SetErrorS("Bad alpha size"); goto fail; } if (s->pitch != AG_ReadUint16(ds)) { AG_SetErrorS("Bad pitch"); goto fail; } if (AG_Read(ds, s->pixels, (h * s->pitch)) != 0) { goto fail; } (void)AG_ReadUint32(ds); /* s->n; TODO */ return (s); fail: AG_SurfaceFree(s); return (NULL); }