diff options
| author | Mike Buland <mike@xagasoft.com> | 2015-04-08 08:40:05 -0600 |
|---|---|---|
| committer | Mike Buland <mike@xagasoft.com> | 2015-04-08 08:40:05 -0600 |
| commit | f314041b6b37bb9274d9fc79946858341befa0f2 (patch) | |
| tree | 3ad385b2bdedeb367ae8b26341d7044c340dc153 /src | |
| parent | 518619603ab3c49b7fdfcf19c439c1a30668164f (diff) | |
| download | lost-f314041b6b37bb9274d9fc79946858341befa0f2.tar.gz lost-f314041b6b37bb9274d9fc79946858341befa0f2.tar.bz2 lost-f314041b6b37bb9274d9fc79946858341befa0f2.tar.xz lost-f314041b6b37bb9274d9fc79946858341befa0f2.zip | |
Added image goo + font support.
Diffstat (limited to '')
| -rw-r--r-- | src/font.cpp | 192 | ||||
| -rw-r--r-- | src/font.h | 65 | ||||
| -rw-r--r-- | src/image.cpp | 143 | ||||
| -rw-r--r-- | src/image.h | 27 | ||||
| -rw-r--r-- | src/main.cpp | 16 | ||||
| -rw-r--r-- | src/palette.cpp | 32 | ||||
| -rw-r--r-- | src/palette.h | 22 | ||||
| -rw-r--r-- | src/renderpng.cpp | 251 |
8 files changed, 657 insertions, 91 deletions
diff --git a/src/font.cpp b/src/font.cpp new file mode 100644 index 0000000..27204a7 --- /dev/null +++ b/src/font.cpp | |||
| @@ -0,0 +1,192 @@ | |||
| 1 | #include "font.h" | ||
| 2 | |||
| 3 | #include <stdio.h> | ||
| 4 | #include <string.h> | ||
| 5 | |||
| 6 | #include <exception> | ||
| 7 | |||
| 8 | #define fh (( (FILE *)rawfh )) | ||
| 9 | |||
| 10 | Font::Font( const char *sSrcFile ) : | ||
| 11 | iTableTop( 0 ), | ||
| 12 | pTable( NULL ) | ||
| 13 | { | ||
| 14 | iTableTop = 128; | ||
| 15 | pTable = new Glyph*[iTableTop]; | ||
| 16 | memset( pTable, 0, sizeof(Glyph*)*iTableTop ); | ||
| 17 | Parser p( sSrcFile, *this ); | ||
| 18 | p.parse(); | ||
| 19 | } | ||
| 20 | |||
| 21 | Font::~Font() | ||
| 22 | { | ||
| 23 | } | ||
| 24 | |||
| 25 | Font::Parser::Parser( const char *sSrcFile, Font &rFont ) : | ||
| 26 | rFont( rFont ), | ||
| 27 | rawfh( NULL ), | ||
| 28 | sLine( NULL ), | ||
| 29 | bDone( false ) | ||
| 30 | { | ||
| 31 | sLine = new char[1024]; | ||
| 32 | rawfh = fopen( sSrcFile, "rt" ); | ||
| 33 | } | ||
| 34 | |||
| 35 | Font::Parser::~Parser() | ||
| 36 | { | ||
| 37 | delete[] sLine; | ||
| 38 | fclose( fh ); | ||
| 39 | } | ||
| 40 | |||
| 41 | void Font::Parser::parse() | ||
| 42 | { | ||
| 43 | header(); | ||
| 44 | characters(); | ||
| 45 | if( strncasecmp("ENDFONT", sLine, 7 ) ) | ||
| 46 | { | ||
| 47 | printf("End of file reached, but no end marker.\n"); | ||
| 48 | throw std::exception(); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | void Font::Parser::getLine() | ||
| 53 | { | ||
| 54 | for(;;) | ||
| 55 | { | ||
| 56 | if( fgets( sLine, 1024, fh ) == NULL ) | ||
| 57 | { | ||
| 58 | sLine[0] = '\0'; | ||
| 59 | bDone = true; | ||
| 60 | printf("Premature end of file.\n"); | ||
| 61 | throw std::exception(); | ||
| 62 | return; | ||
| 63 | } | ||
| 64 | |||
| 65 | if( strncasecmp("COMMENT ", sLine, 8 ) ) | ||
| 66 | { | ||
| 67 | return; | ||
| 68 | } | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | void Font::Parser::header() | ||
| 73 | { | ||
| 74 | getLine(); | ||
| 75 | if( strncasecmp("STARTFONT 2.1", sLine, 13 ) ) | ||
| 76 | { | ||
| 77 | printf("Bad format: %s\n", sLine); | ||
| 78 | throw std::exception(); | ||
| 79 | } | ||
| 80 | |||
| 81 | for(;;) | ||
| 82 | { | ||
| 83 | getLine(); | ||
| 84 | if( strncasecmp("SIZE ", sLine, 5 ) == 0 ) | ||
| 85 | { | ||
| 86 | } | ||
| 87 | else if( strncasecmp("FONTBOUNDINGBOX ", sLine, 16 ) == 0 ) | ||
| 88 | { | ||
| 89 | } | ||
| 90 | else if( strncasecmp("STARTPROPERTIES ", sLine, 16 ) == 0 ) | ||
| 91 | { | ||
| 92 | properties(); | ||
| 93 | } | ||
| 94 | else if( strncasecmp("CHARS ", sLine, 6 ) == 0 ) | ||
| 95 | { | ||
| 96 | return; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | void Font::Parser::properties() | ||
| 102 | { | ||
| 103 | for(;;) | ||
| 104 | { | ||
| 105 | getLine(); | ||
| 106 | if( strncasecmp("ENDPROPERTIES", sLine, 13 ) == 0 ) | ||
| 107 | return; | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | void Font::Parser::characters() | ||
| 112 | { | ||
| 113 | for(;;) | ||
| 114 | { | ||
| 115 | getLine(); | ||
| 116 | if( strncasecmp("STARTCHAR ", sLine, 10 ) == 0 ) | ||
| 117 | character(); | ||
| 118 | else | ||
| 119 | return; | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | uint8_t hex2byte( const char *str ) | ||
| 124 | { | ||
| 125 | uint8_t ret = 0; | ||
| 126 | |||
| 127 | ret |= ((*str >= '0' && *str <= '9')?(*str-'0'):( | ||
| 128 | (*str >= 'a' && *str <= 'f')?(*str-'a'+10):( | ||
| 129 | (*str >= 'A' && *str <= 'F')?(*str-'A'+10):0 | ||
| 130 | )))<<4; | ||
| 131 | str++; | ||
| 132 | ret |= (*str >= '0' && *str <= '9')?(*str-'0'):( | ||
| 133 | (*str >= 'a' && *str <= 'f')?(*str-'a'+10):( | ||
| 134 | (*str >= 'A' && *str <= 'F')?(*str-'A'+10):0 | ||
| 135 | )); | ||
| 136 | return ret; | ||
| 137 | } | ||
| 138 | |||
| 139 | void Font::Parser::character() | ||
| 140 | { | ||
| 141 | char sName[1024]; | ||
| 142 | int32_t iIdx = -1; | ||
| 143 | strcpy( sName, sLine+10 ); | ||
| 144 | Glyph *pChar = new Glyph(); | ||
| 145 | |||
| 146 | for(;;) | ||
| 147 | { | ||
| 148 | getLine(); | ||
| 149 | if( strncasecmp("ENCODING ", sLine, 9 ) == 0 ) | ||
| 150 | { | ||
| 151 | sscanf( sLine+9, "%d", &iIdx ); | ||
| 152 | } | ||
| 153 | else if( strncasecmp("DWIDTH ", sLine, 7 ) == 0 ) | ||
| 154 | { | ||
| 155 | sscanf( sLine+7, "%d %d", &pChar->pDevOff.x, &pChar->pDevOff.y ); | ||
| 156 | } | ||
| 157 | else if( strncasecmp("BBX ", sLine, 4 ) == 0 ) | ||
| 158 | { | ||
| 159 | sscanf( sLine+4, "%d %d %d %d", | ||
| 160 | &pChar->pBox.x, &pChar->pBox.y, | ||
| 161 | &pChar->pOff.x, &pChar->pOff.y | ||
| 162 | ); | ||
| 163 | } | ||
| 164 | else if( strncasecmp("BITMAP", sLine, 6 ) == 0 ) | ||
| 165 | { | ||
| 166 | pChar->iRowBytes = pChar->pBox.x/8 + ((pChar->pBox.x%8)==0?0:1); | ||
| 167 | |||
| 168 | pChar->pData = new uint8_t[pChar->iRowBytes*pChar->pBox.y]; | ||
| 169 | // Read bitmap | ||
| 170 | for( int y = 0; y < pChar->pBox.y; y++ ) | ||
| 171 | { | ||
| 172 | getLine(); | ||
| 173 | for( int x = 0; x < pChar->iRowBytes; x++ ) | ||
| 174 | { | ||
| 175 | pChar->pData[x+y*pChar->iRowBytes] = hex2byte( sLine+(2*x) ); | ||
| 176 | } | ||
| 177 | } | ||
| 178 | } | ||
| 179 | else if( strncasecmp("ENDCHAR", sLine, 7 ) == 0 ) | ||
| 180 | { | ||
| 181 | if( iIdx >= 0 && iIdx < rFont.iTableTop ) | ||
| 182 | { | ||
| 183 | rFont.pTable[iIdx] = pChar; | ||
| 184 | //printf("Char %d: %s\n", iIdx, sName ); | ||
| 185 | } | ||
| 186 | else | ||
| 187 | delete pChar; | ||
| 188 | return; | ||
| 189 | } | ||
| 190 | } | ||
| 191 | } | ||
| 192 | |||
diff --git a/src/font.h b/src/font.h new file mode 100644 index 0000000..802de9d --- /dev/null +++ b/src/font.h | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | #ifndef FONT_H | ||
| 2 | #define FONT_H | ||
| 3 | |||
| 4 | #include <stdint.h> | ||
| 5 | |||
| 6 | class Font | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | class Point | ||
| 10 | { | ||
| 11 | public: | ||
| 12 | int32_t x, y; | ||
| 13 | }; | ||
| 14 | |||
| 15 | class Glyph | ||
| 16 | { | ||
| 17 | public: | ||
| 18 | Glyph() : | ||
| 19 | pData( NULL ) | ||
| 20 | { } | ||
| 21 | ~Glyph() | ||
| 22 | { delete[] pData; } | ||
| 23 | Point pBox; | ||
| 24 | Point pOff; | ||
| 25 | Point pDevOff; | ||
| 26 | |||
| 27 | int iRowBytes; | ||
| 28 | uint8_t *pData; | ||
| 29 | }; | ||
| 30 | |||
| 31 | public: | ||
| 32 | Font( const char *sSrcFile ); | ||
| 33 | virtual ~Font(); | ||
| 34 | |||
| 35 | Glyph *get( char c ) { return pTable[(int32_t)c]; } | ||
| 36 | |||
| 37 | private: | ||
| 38 | Point pDefBox; | ||
| 39 | Point pDefOff; | ||
| 40 | int32_t iTableTop; | ||
| 41 | Glyph **pTable; | ||
| 42 | |||
| 43 | private: // Parser | ||
| 44 | class Parser | ||
| 45 | { | ||
| 46 | public: | ||
| 47 | Parser( const char *sSrcFile, Font &rFont ); | ||
| 48 | ~Parser(); | ||
| 49 | |||
| 50 | void parse(); | ||
| 51 | void getLine(); | ||
| 52 | void header(); | ||
| 53 | void properties(); | ||
| 54 | void characters(); | ||
| 55 | void character(); | ||
| 56 | |||
| 57 | private: | ||
| 58 | Font &rFont; | ||
| 59 | void *rawfh; | ||
| 60 | char *sLine; | ||
| 61 | bool bDone; | ||
| 62 | }; | ||
| 63 | }; | ||
| 64 | |||
| 65 | #endif | ||
diff --git a/src/image.cpp b/src/image.cpp new file mode 100644 index 0000000..384de9a --- /dev/null +++ b/src/image.cpp | |||
| @@ -0,0 +1,143 @@ | |||
| 1 | #include "image.h" | ||
| 2 | #include "palette.h" | ||
| 3 | #include "font.h" | ||
| 4 | |||
| 5 | #include <stdlib.h> | ||
| 6 | #include <string.h> | ||
| 7 | #include <png.h> | ||
| 8 | |||
| 9 | Image::Image() : | ||
| 10 | iWidth( 0 ), | ||
| 11 | iHeight( 0 ), | ||
| 12 | pPix( NULL ) | ||
| 13 | { | ||
| 14 | } | ||
| 15 | |||
| 16 | Image::Image( int32_t iWidth, int32_t iHeight ) : | ||
| 17 | iWidth( iWidth ), | ||
| 18 | iHeight( iHeight ), | ||
| 19 | pPix( NULL ) | ||
| 20 | { | ||
| 21 | pPix = new uint8_t[iWidth*iHeight]; | ||
| 22 | clear(); | ||
| 23 | } | ||
| 24 | |||
| 25 | Image::~Image() | ||
| 26 | { | ||
| 27 | delete[] pPix; | ||
| 28 | } | ||
| 29 | |||
| 30 | void Image::clear( uint8_t uColor ) | ||
| 31 | { | ||
| 32 | memset( pPix, uColor, iWidth*iHeight ); | ||
| 33 | } | ||
| 34 | |||
| 35 | void Image::set( int32_t x, int32_t y, uint8_t iCol ) | ||
| 36 | { | ||
| 37 | if( x < 0 || y < 0 || x >= iWidth || y >= iHeight ) | ||
| 38 | return; | ||
| 39 | |||
| 40 | pPix[x+y*iWidth] = iCol; | ||
| 41 | } | ||
| 42 | |||
| 43 | void Image::save( const char *sPath, class Palette &rPal ) | ||
| 44 | { | ||
| 45 | uint8_t **pRows = new uint8_t*[iHeight]; | ||
| 46 | for( int r = 0; r < iHeight; r++ ) | ||
| 47 | { | ||
| 48 | pRows[r] = pPix+(iWidth*r); | ||
| 49 | } | ||
| 50 | |||
| 51 | png_structp png_ptr = png_create_write_struct( | ||
| 52 | PNG_LIBPNG_VER_STRING, NULL, NULL, NULL | ||
| 53 | ); | ||
| 54 | png_infop info_ptr = png_create_info_struct(png_ptr); | ||
| 55 | png_set_IHDR(png_ptr, info_ptr, iWidth, iHeight, | ||
| 56 | 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, | ||
| 57 | PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT | ||
| 58 | ); | ||
| 59 | png_color *pCol = new png_color[rPal.getCount()]; | ||
| 60 | for( int j = 0; j < rPal.getCount(); j++ ) | ||
| 61 | { | ||
| 62 | uint8_t r, g, b; | ||
| 63 | rPal.getColor( j, r, g, b ); | ||
| 64 | pCol[j].red = r; | ||
| 65 | pCol[j].green = g; | ||
| 66 | pCol[j].blue = b; | ||
| 67 | } | ||
| 68 | png_set_PLTE( png_ptr, info_ptr, pCol, rPal.getCount()); | ||
| 69 | |||
| 70 | png_set_rows( png_ptr, info_ptr, pRows ); | ||
| 71 | |||
| 72 | FILE *fp = fopen(sPath, "wb"); | ||
| 73 | if( fp == NULL ) | ||
| 74 | { | ||
| 75 | printf("Error opening file!\n"); | ||
| 76 | exit( 1 ); | ||
| 77 | } | ||
| 78 | |||
| 79 | png_init_io( png_ptr, fp ); | ||
| 80 | png_write_png( png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL ); | ||
| 81 | png_destroy_write_struct( &png_ptr, &info_ptr ); | ||
| 82 | fclose( fp ); | ||
| 83 | |||
| 84 | delete[] pCol; | ||
| 85 | delete[] pRows; | ||
| 86 | } | ||
| 87 | |||
| 88 | void Image::drawText( class Font &rFnt, int32_t x, int32_t y, uint8_t uColor, | ||
| 89 | const char *sText ) | ||
| 90 | { | ||
| 91 | for( const char *s = sText; *s; s++ ) | ||
| 92 | { | ||
| 93 | Font::Glyph *pGlyph = rFnt.get( *s ); | ||
| 94 | if( pGlyph == NULL ) | ||
| 95 | continue; | ||
| 96 | |||
| 97 | for( int cy = 0; cy < pGlyph->pBox.y; cy++ ) | ||
| 98 | { | ||
| 99 | for( int cx = 0; cx < pGlyph->pBox.x; cx++ ) | ||
| 100 | { | ||
| 101 | int bit = 1<<(7-(cx%8)); | ||
| 102 | int byte = cx/8; | ||
| 103 | if( pGlyph->pData[byte+cy*pGlyph->iRowBytes]&bit ) | ||
| 104 | set( x+cx, y+cy-pGlyph->pBox.y-pGlyph->pOff.y, uColor ); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | x += pGlyph->pDevOff.x; | ||
| 108 | y += pGlyph->pDevOff.y; | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 112 | void Image::drawLine( int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint8_t uColor ) | ||
| 113 | { | ||
| 114 | if( x1 == x2 ) | ||
| 115 | { | ||
| 116 | // Vertical line, easy | ||
| 117 | if( y2 < y1 ) | ||
| 118 | { | ||
| 119 | int32_t r = y2; | ||
| 120 | y2 = y1; | ||
| 121 | y1 = r; | ||
| 122 | } | ||
| 123 | for( int j = y1; j <= y2; j++ ) | ||
| 124 | { | ||
| 125 | set( x1, j, uColor ); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | else if( y1 == y2 ) | ||
| 129 | { | ||
| 130 | // Horizontal line, easy | ||
| 131 | if( x2 < x1 ) | ||
| 132 | { | ||
| 133 | int32_t r = x2; | ||
| 134 | x2 = x1; | ||
| 135 | x1 = r; | ||
| 136 | } | ||
| 137 | for( int j = x1; j <= x2; j++ ) | ||
| 138 | { | ||
| 139 | set( j, y1, uColor ); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
diff --git a/src/image.h b/src/image.h new file mode 100644 index 0000000..cdc13e0 --- /dev/null +++ b/src/image.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | #ifndef IMAGE_H | ||
| 2 | #define IMAGE_H | ||
| 3 | |||
| 4 | #include <stdint.h> | ||
| 5 | |||
| 6 | class Image | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | Image(); | ||
| 10 | Image( int32_t iWidth, int32_t iHeight ); | ||
| 11 | virtual ~Image(); | ||
| 12 | |||
| 13 | void clear( uint8_t uColor=0 ); | ||
| 14 | void set( int32_t x, int32_t y, uint8_t iCol ); | ||
| 15 | |||
| 16 | void save( const char *sPath, class Palette &rPal ); | ||
| 17 | void drawText( class Font &rFnt, int32_t x, int32_t y, uint8_t uColor, | ||
| 18 | const char *sText ); | ||
| 19 | void drawLine( int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint8_t uColor ); | ||
| 20 | |||
| 21 | private: | ||
| 22 | int32_t iWidth; | ||
| 23 | int32_t iHeight; | ||
| 24 | uint8_t *pPix; | ||
| 25 | }; | ||
| 26 | |||
| 27 | #endif | ||
diff --git a/src/main.cpp b/src/main.cpp index ef3f3de..00dfc8b 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
| @@ -10,8 +10,24 @@ | |||
| 10 | #include <stdlib.h> | 10 | #include <stdlib.h> |
| 11 | #include <time.h> | 11 | #include <time.h> |
| 12 | 12 | ||
| 13 | #include "image.h" | ||
| 14 | #include "palette.h" | ||
| 15 | #include "font.h" | ||
| 16 | |||
| 13 | int main( int argc, char *argv[] ) | 17 | int main( int argc, char *argv[] ) |
| 14 | { | 18 | { |
| 19 | /* | ||
| 20 | Image im( 400, 400 ); | ||
| 21 | Font f("ter-u12n.bdf"); | ||
| 22 | Palette pl; | ||
| 23 | pl.addColor( 0, 0, 0 ); | ||
| 24 | pl.addColor( 255, 0, 0 ); | ||
| 25 | pl.addColor( 0, 0, 255 ); | ||
| 26 | im.drawLine( 0, 12, 399, 12, 2 ); | ||
| 27 | im.drawText( f, 12, 12, 1, "Hello World!yqjm (01234,56789)"); | ||
| 28 | im.save("test.png", pl); | ||
| 29 | return 0; | ||
| 30 | */ | ||
| 15 | srand( time( NULL ) ); | 31 | srand( time( NULL ) ); |
| 16 | 32 | ||
| 17 | if( argc <= 2 ) | 33 | if( argc <= 2 ) |
diff --git a/src/palette.cpp b/src/palette.cpp new file mode 100644 index 0000000..0e3a3b1 --- /dev/null +++ b/src/palette.cpp | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | #include "palette.h" | ||
| 2 | |||
| 3 | #include <string.h> | ||
| 4 | |||
| 5 | Palette::Palette() : | ||
| 6 | iCount( 0 ), | ||
| 7 | piChannels( NULL ) | ||
| 8 | { | ||
| 9 | piChannels = new uint8_t[256*3]; | ||
| 10 | memset( piChannels, 0, 256*3 ); | ||
| 11 | } | ||
| 12 | |||
| 13 | Palette::~Palette() | ||
| 14 | { | ||
| 15 | delete[] piChannels; | ||
| 16 | } | ||
| 17 | |||
| 18 | int32_t Palette::addColor( uint8_t iRed, uint8_t iGreen, uint8_t iBlue ) | ||
| 19 | { | ||
| 20 | piChannels[iCount*3] = iRed; | ||
| 21 | piChannels[iCount*3+1] = iGreen; | ||
| 22 | piChannels[iCount*3+2] = iBlue; | ||
| 23 | return iCount++; | ||
| 24 | } | ||
| 25 | |||
| 26 | void Palette::getColor( int32_t iIdx, uint8_t &iRed, uint8_t &iGreen, | ||
| 27 | uint8_t &iBlue ) | ||
| 28 | { | ||
| 29 | iRed = piChannels[iIdx*3]; | ||
| 30 | iGreen = piChannels[iIdx*3+1]; | ||
| 31 | iBlue = piChannels[iIdx*3+2]; | ||
| 32 | } | ||
diff --git a/src/palette.h b/src/palette.h new file mode 100644 index 0000000..3fb176a --- /dev/null +++ b/src/palette.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | #ifndef PALETTE_H | ||
| 2 | #define PALETTE_H | ||
| 3 | |||
| 4 | #include <stdint.h> | ||
| 5 | |||
| 6 | class Palette | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | Palette(); | ||
| 10 | virtual ~Palette(); | ||
| 11 | |||
| 12 | int32_t addColor( uint8_t iRed, uint8_t iGreen, uint8_t iBlue ); | ||
| 13 | int32_t getCount() const { return iCount; } | ||
| 14 | void getColor( int32_t iIdx, uint8_t &iRed, uint8_t &iGreen, | ||
| 15 | uint8_t &iBlue ); | ||
| 16 | |||
| 17 | private: | ||
| 18 | int32_t iCount; | ||
| 19 | uint8_t *piChannels; | ||
| 20 | }; | ||
| 21 | |||
| 22 | #endif | ||
diff --git a/src/renderpng.cpp b/src/renderpng.cpp index 21d35ba..6ff9fbe 100644 --- a/src/renderpng.cpp +++ b/src/renderpng.cpp | |||
| @@ -3,11 +3,15 @@ | |||
| 3 | #include "map.h" | 3 | #include "map.h" |
| 4 | #include "cell.h" | 4 | #include "cell.h" |
| 5 | 5 | ||
| 6 | #include "image.h" | ||
| 7 | #include "palette.h" | ||
| 8 | #include "font.h" | ||
| 9 | |||
| 6 | #include <math.h> | 10 | #include <math.h> |
| 7 | #include <string.h> | 11 | #include <string.h> |
| 8 | #include <stdint.h> | 12 | #include <stdint.h> |
| 9 | #include <stdlib.h> | 13 | #include <stdlib.h> |
| 10 | #include <png.h> | 14 | #include <stdio.h> |
| 11 | 15 | ||
| 12 | RenderPng::RenderPng( Map &rMap ) : | 16 | RenderPng::RenderPng( Map &rMap ) : |
| 13 | rMap( rMap ) | 17 | rMap( rMap ) |
| @@ -25,16 +29,18 @@ void RenderPng::render() | |||
| 25 | if( iDims > 2 ) | 29 | if( iDims > 2 ) |
| 26 | iSize = (int)ceil(sqrt((rMap.getDims()-2)*2)); | 30 | iSize = (int)ceil(sqrt((rMap.getDims()-2)*2)); |
| 27 | 31 | ||
| 28 | int iBufWidth = ((iSize+1)*rMap.getSize( 0 )+1)*5; | 32 | int iCellSize = 11; |
| 29 | int iBufHeight = ((iSize+1)*rMap.getSize( 1 )+1)*5; | 33 | int iCellMid = iCellSize/2; |
| 30 | int iBufSize = iBufWidth*iBufHeight; | 34 | int iBufWidth = ((iSize+1)*rMap.getSize( 0 )+1)*iCellSize; |
| 31 | uint8_t *pBuf = new uint8_t[iBufSize]; | 35 | int iBufHeight = ((iSize+1)*rMap.getSize( 1 )+1)*iCellSize+12; |
| 32 | uint8_t **pRows = new uint8_t*[iBufHeight]; | 36 | int ox = 0; |
| 33 | for( int r = 0; r < iBufHeight; r++ ) | 37 | int oy = 12; |
| 34 | { | 38 | Image im( iBufWidth, iBufHeight ); |
| 35 | pRows[r] = pBuf+(iBufWidth*r); | 39 | Font fnt("ter-u12n.bdf"); |
| 36 | } | 40 | im.clear( 1 ); |
| 37 | memset( pBuf, 1, iBufSize ); | 41 | Palette pal; |
| 42 | pal.addColor( 0, 0, 0 ); | ||
| 43 | pal.addColor( 255, 255, 255 ); | ||
| 38 | 44 | ||
| 39 | Position p( iDims ); | 45 | Position p( iDims ); |
| 40 | for(;;) | 46 | for(;;) |
| @@ -50,86 +56,138 @@ void RenderPng::render() | |||
| 50 | if( (iRow == 0 || iRow == iSize+1) && | 56 | if( (iRow == 0 || iRow == iSize+1) && |
| 51 | (iCol == 0 || iCol == iSize+1) ) | 57 | (iCol == 0 || iCol == iSize+1) ) |
| 52 | { | 58 | { |
| 53 | pRows[(y+iRow)*5+2][(x+iCol)*5+2] = 0; | 59 | im.set( |
| 60 | ox+(x+iCol)*iCellSize+iCellMid, | ||
| 61 | oy+(y+iRow)*iCellSize+iCellMid, | ||
| 62 | 0 | ||
| 63 | ); | ||
| 54 | if( iRow == 0 && iCol == 0 ) | 64 | if( iRow == 0 && iCol == 0 ) |
| 55 | { | 65 | { |
| 56 | if( (iWalls&(1<<2)) == 0 ) | 66 | if( (iWalls&(1<<2)) == 0 ) |
| 57 | { | 67 | { |
| 58 | for( int i = 0; i < 3; i++ ) | 68 | for( int i = 0; i < iCellMid+1; i++ ) |
| 59 | pRows[(y+iRow)*5+2][(x+iCol)*5+i+3] = 0; | 69 | im.set( |
| 70 | ox+(x+iCol)*iCellSize+i+iCellMid+1, | ||
| 71 | oy+(y+iRow)*iCellSize+iCellMid, | ||
| 72 | 0 | ||
| 73 | ); | ||
| 60 | } | 74 | } |
| 61 | if( (iWalls&(1<<0)) == 0 ) | 75 | if( (iWalls&(1<<0)) == 0 ) |
| 62 | { | 76 | { |
| 63 | for( int i = 0; i < 3; i++ ) | 77 | for( int i = 0; i < iCellMid+1; i++ ) |
| 64 | pRows[(y+iRow)*5+i+3][(x+iCol)*5+2] = 0; | 78 | im.set( |
| 79 | ox+(x+iCol)*iCellSize+iCellMid, | ||
| 80 | oy+(y+iRow)*iCellSize+i+iCellMid+1, | ||
| 81 | 0 | ||
| 82 | ); | ||
| 65 | } | 83 | } |
| 66 | } | 84 | } |
| 67 | else if( iRow == 0 && iCol == iSize+1 ) | 85 | else if( iRow == 0 && iCol == iSize+1 ) |
| 68 | { | 86 | { |
| 69 | if( (iWalls&(1<<2)) == 0 ) | 87 | if( (iWalls&(1<<2)) == 0 ) |
| 70 | { | 88 | { |
| 71 | for( int i = 0; i < 3; i++ ) | 89 | for( int i = 0; i < iCellMid+1; i++ ) |
| 72 | pRows[(y+iRow)*5+2][(x+iCol)*5+i] = 0; | 90 | im.set( |
| 91 | ox+(x+iCol)*iCellSize+i, | ||
| 92 | oy+(y+iRow)*iCellSize+iCellMid, | ||
| 93 | 0 | ||
| 94 | ); | ||
| 73 | } | 95 | } |
| 74 | if( (iWalls&(1<<1)) == 0 ) | 96 | if( (iWalls&(1<<1)) == 0 ) |
| 75 | { | 97 | { |
| 76 | for( int i = 0; i < 3; i++ ) | 98 | for( int i = 0; i < iCellMid+1; i++ ) |
| 77 | pRows[(y+iRow)*5+i+3][(x+iCol)*5+2] = 0; | 99 | im.set( |
| 100 | ox+(x+iCol)*iCellSize+iCellMid, | ||
| 101 | oy+(y+iRow)*iCellSize+i+iCellMid+1, | ||
| 102 | 0 | ||
| 103 | ); | ||
| 78 | } | 104 | } |
| 79 | } | 105 | } |
| 80 | else if( iRow == iSize+1 && iCol == 0 ) | 106 | else if( iRow == iSize+1 && iCol == 0 ) |
| 81 | { | 107 | { |
| 82 | if( (iWalls&(1<<3)) == 0 ) | 108 | if( (iWalls&(1<<3)) == 0 ) |
| 83 | { | 109 | { |
| 84 | for( int i = 0; i < 3; i++ ) | 110 | for( int i = 0; i < iCellMid+1; i++ ) |
| 85 | pRows[(y+iRow)*5+2][(x+iCol)*5+i+3] = 0; | 111 | im.set( |
| 112 | ox+(x+iCol)*iCellSize+i+iCellMid+1, | ||
| 113 | oy+(y+iRow)*iCellSize+iCellMid, | ||
| 114 | 0 | ||
| 115 | ); | ||
| 86 | } | 116 | } |
| 87 | if( (iWalls&(1<<0)) == 0 ) | 117 | if( (iWalls&(1<<0)) == 0 ) |
| 88 | { | 118 | { |
| 89 | for( int i = 0; i < 3; i++ ) | 119 | for( int i = 0; i < iCellMid+1; i++ ) |
| 90 | pRows[(y+iRow)*5+i][(x+iCol)*5+2] = 0; | 120 | im.set( |
| 121 | ox+(x+iCol)*iCellSize+iCellMid, | ||
| 122 | oy+(y+iRow)*iCellSize+i, | ||
| 123 | 0 | ||
| 124 | ); | ||
| 91 | } | 125 | } |
| 92 | } | 126 | } |
| 93 | else if( iRow == iSize+1 && iCol == iSize+1 ) | 127 | else if( iRow == iSize+1 && iCol == iSize+1 ) |
| 94 | { | 128 | { |
| 95 | if( (iWalls&(1<<3)) == 0 ) | 129 | if( (iWalls&(1<<3)) == 0 ) |
| 96 | { | 130 | { |
| 97 | for( int i = 0; i < 3; i++ ) | 131 | for( int i = 0; i < iCellMid+1; i++ ) |
| 98 | pRows[(y+iRow)*5+2][(x+iCol)*5+i] = 0; | 132 | im.set( |
| 133 | ox+(x+iCol)*iCellSize+i, | ||
| 134 | oy+(y+iRow)*iCellSize+iCellMid, | ||
| 135 | 0 | ||
| 136 | ); | ||
| 99 | } | 137 | } |
| 100 | if( (iWalls&(1<<1)) == 0 ) | 138 | if( (iWalls&(1<<1)) == 0 ) |
| 101 | { | 139 | { |
| 102 | for( int i = 0; i < 3; i++ ) | 140 | for( int i = 0; i < iCellMid+1; i++ ) |
| 103 | pRows[(y+iRow)*5+i][(x+iCol)*5+2] = 0; | 141 | im.set( |
| 142 | ox+(x+iCol)*iCellSize+iCellMid, | ||
| 143 | oy+(y+iRow)*iCellSize+i, | ||
| 144 | 0 | ||
| 145 | ); | ||
| 104 | } | 146 | } |
| 105 | } | 147 | } |
| 106 | } | 148 | } |
| 107 | else if( iRow == 0 && (iWalls&(1<<2)) == 0 ) | 149 | else if( iRow == 0 && (iWalls&(1<<2)) == 0 ) |
| 108 | { | 150 | { |
| 109 | for( int i = 0; i < 5; i++ ) | 151 | for( int i = 0; i < iCellSize; i++ ) |
| 110 | { | 152 | { |
| 111 | pRows[(y+iRow)*5+2][(x+iCol)*5+i] = 0; | 153 | im.set( |
| 154 | ox+(x+iCol)*iCellSize+i, | ||
| 155 | oy+(y+iRow)*iCellSize+iCellMid, | ||
| 156 | 0 | ||
| 157 | ); | ||
| 112 | } | 158 | } |
| 113 | } | 159 | } |
| 114 | else if( iRow == iSize+1 && (iWalls&(1<<3)) == 0 ) | 160 | else if( iRow == iSize+1 && (iWalls&(1<<3)) == 0 ) |
| 115 | { | 161 | { |
| 116 | for( int i = 0; i < 5; i++ ) | 162 | for( int i = 0; i < iCellSize; i++ ) |
| 117 | { | 163 | { |
| 118 | pRows[(y+iRow)*5+2][(x+iCol)*5+i] = 0; | 164 | im.set( |
| 165 | ox+(x+iCol)*iCellSize+i, | ||
| 166 | oy+(y+iRow)*iCellSize+iCellMid, | ||
| 167 | 0 | ||
| 168 | ); | ||
| 119 | } | 169 | } |
| 120 | } | 170 | } |
| 121 | else if( iCol == 0 && (iWalls&(1<<0)) == 0 ) | 171 | else if( iCol == 0 && (iWalls&(1<<0)) == 0 ) |
| 122 | { | 172 | { |
| 123 | for( int i = 0; i < 5; i++ ) | 173 | for( int i = 0; i < iCellSize; i++ ) |
| 124 | { | 174 | { |
| 125 | pRows[(y+iRow)*5+i][(x+iCol)*5+2] = 0; | 175 | im.set( |
| 176 | ox+(x+iCol)*iCellSize+iCellMid, | ||
| 177 | oy+(y+iRow)*iCellSize+i, | ||
| 178 | 0 | ||
| 179 | ); | ||
| 126 | } | 180 | } |
| 127 | } | 181 | } |
| 128 | else if( iCol == iSize+1 && (iWalls&(1<<1)) == 0 ) | 182 | else if( iCol == iSize+1 && (iWalls&(1<<1)) == 0 ) |
| 129 | { | 183 | { |
| 130 | for( int i = 0; i < 5; i++ ) | 184 | for( int i = 0; i < iCellSize; i++ ) |
| 131 | { | 185 | { |
| 132 | pRows[(y+iRow)*5+i][(x+iCol)*5+2] = 0; | 186 | im.set( |
| 187 | ox+(x+iCol)*iCellSize+iCellMid, | ||
| 188 | oy+(y+iRow)*iCellSize+i, | ||
| 189 | 0 | ||
| 190 | ); | ||
| 133 | } | 191 | } |
| 134 | } | 192 | } |
| 135 | } | 193 | } |
| @@ -142,43 +200,73 @@ void RenderPng::render() | |||
| 142 | int d = j*2+side; | 200 | int d = j*2+side; |
| 143 | if( iWalls&(1<<d) ) | 201 | if( iWalls&(1<<d) ) |
| 144 | { | 202 | { |
| 145 | int iSubX = (x+1+((d-4)%iSize))*5; | 203 | int iSubX = (x+1+((d-4)%iSize))*iCellSize; |
| 146 | int iSubY = (y+1+((d-4)/iSize))*5; | 204 | int iSubY = (y+1+((d-4)/iSize))*iCellSize; |
| 147 | // | 205 | |
| 148 | // char &c = buf[x+1+iSubX+(y+1+iSubY)*iBufWidth]; | ||
| 149 | // c = cPassages[d]; | ||
| 150 | switch( d ) | 206 | switch( d ) |
| 151 | { | 207 | { |
| 152 | case 4: | 208 | case 4: |
| 153 | pRows[iSubY+1][iSubX+2] = 0; | 209 | im.set( ox+iSubX+iCellMid, oy+iSubY+1, 0 ); |
| 154 | pRows[iSubY+2][iSubX+1] = 0; | 210 | for( int m = 0; m < iCellMid; m++ ) |
| 155 | pRows[iSubY+2][iSubX+3] = 0; | 211 | { |
| 156 | pRows[iSubY+3][iSubX+0] = 0; | 212 | im.set( ox+iSubX+m, oy+iSubY+iCellMid-m+1, 0 ); |
| 157 | pRows[iSubY+3][iSubX+4] = 0; | 213 | im.set( ox+iSubX+iCellMid+m+1, oy+iSubY+m+2, 0 ); |
| 214 | } | ||
| 215 | /* | ||
| 216 | im.set( iSubX+2, iSubY+1, 0 ); | ||
| 217 | im.set( iSubX+1, iSubY+2, 0 ); | ||
| 218 | im.set( iSubX+3, iSubY+2, 0 ); | ||
| 219 | im.set( iSubX+0, iSubY+3, 0 ); | ||
| 220 | im.set( iSubX+4, iSubY+3, 0 ); | ||
| 221 | */ | ||
| 158 | break; | 222 | break; |
| 159 | 223 | ||
| 160 | case 5: | 224 | case 5: |
| 161 | pRows[iSubY+3][iSubX+2] = 0; | 225 | im.set( ox+iSubX+iCellMid, oy+iSubY+iCellSize-2, 0 ); |
| 162 | pRows[iSubY+2][iSubX+1] = 0; | 226 | for( int m = 0; m < iCellMid; m++ ) |
| 163 | pRows[iSubY+2][iSubX+3] = 0; | 227 | { |
| 164 | pRows[iSubY+1][iSubX+0] = 0; | 228 | im.set( ox+iSubX+m, oy+iSubY+iCellMid+m-1, 0 ); |
| 165 | pRows[iSubY+1][iSubX+4] = 0; | 229 | im.set( ox+iSubX+iCellMid+m+1, oy+iSubY+iCellSize-m-3, 0 ); |
| 230 | } | ||
| 231 | /* | ||
| 232 | im.set( iSubX+2, iSubY+3, 0 ); | ||
| 233 | im.set( iSubX+1, iSubY+2, 0 ); | ||
| 234 | im.set( iSubX+3, iSubY+2, 0 ); | ||
| 235 | im.set( iSubX+0, iSubY+1, 0 ); | ||
| 236 | im.set( iSubX+4, iSubY+1, 0 ); | ||
| 237 | */ | ||
| 166 | break; | 238 | break; |
| 167 | 239 | ||
| 168 | case 6: | 240 | case 6: |
| 169 | pRows[iSubY+2][iSubX+1] = 0; | 241 | im.set( ox+iSubX+1, oy+iSubY+iCellMid, 0 ); |
| 170 | pRows[iSubY+1][iSubX+2] = 0; | 242 | for( int m = 0; m < iCellMid; m++ ) |
| 171 | pRows[iSubY+3][iSubX+2] = 0; | 243 | { |
| 172 | pRows[iSubY+0][iSubX+3] = 0; | 244 | im.set( ox+iSubX+iCellMid-m+1, oy+iSubY+m, 0 ); |
| 173 | pRows[iSubY+4][iSubX+3] = 0; | 245 | im.set( ox+iSubX+m+2, oy+iSubY+iCellMid+m+1, 0 ); |
| 246 | } | ||
| 247 | /* | ||
| 248 | im.set( iSubX+1, iSubY+2, 0 ); | ||
| 249 | im.set( iSubX+2, iSubY+1, 0 ); | ||
| 250 | im.set( iSubX+2, iSubY+3, 0 ); | ||
| 251 | im.set( iSubX+3, iSubY+0, 0 ); | ||
| 252 | im.set( iSubX+3, iSubY+4, 0 ); | ||
| 253 | */ | ||
| 174 | break; | 254 | break; |
| 175 | 255 | ||
| 176 | case 7: | 256 | case 7: |
| 177 | pRows[iSubY+2][iSubX+3] = 0; | 257 | im.set( ox+iSubX+iCellSize-2, oy+iSubY+iCellMid, 0 ); |
| 178 | pRows[iSubY+1][iSubX+2] = 0; | 258 | for( int m = 0; m < iCellMid; m++ ) |
| 179 | pRows[iSubY+3][iSubX+2] = 0; | 259 | { |
| 180 | pRows[iSubY+0][iSubX+1] = 0; | 260 | im.set( ox+iSubX+iCellMid+m-1, oy+iSubY+m, 0 ); |
| 181 | pRows[iSubY+4][iSubX+1] = 0; | 261 | im.set( ox+iSubX+iCellSize-m-3, oy+iSubY+iCellMid+m+1, 0 ); |
| 262 | } | ||
| 263 | /* | ||
| 264 | im.set( iSubX+3, iSubY+2, 0 ); | ||
| 265 | im.set( iSubX+2, iSubY+1, 0 ); | ||
| 266 | im.set( iSubX+2, iSubY+3, 0 ); | ||
| 267 | im.set( iSubX+1, iSubY+0, 0 ); | ||
| 268 | im.set( iSubX+1, iSubY+4, 0 ); | ||
| 269 | */ | ||
| 182 | break; | 270 | break; |
| 183 | } | 271 | } |
| 184 | } | 272 | } |
| @@ -187,6 +275,7 @@ void RenderPng::render() | |||
| 187 | 275 | ||
| 188 | int iDim; | 276 | int iDim; |
| 189 | char fname[1024]; | 277 | char fname[1024]; |
| 278 | char title[1024]; | ||
| 190 | for( iDim = 0; iDim < iDims; iDim++ ) | 279 | for( iDim = 0; iDim < iDims; iDim++ ) |
| 191 | { | 280 | { |
| 192 | if( ++p[iDim] < rMap.getSize( iDim ) ) | 281 | if( ++p[iDim] < rMap.getSize( iDim ) ) |
| @@ -200,43 +289,25 @@ void RenderPng::render() | |||
| 200 | char buf[1024]; | 289 | char buf[1024]; |
| 201 | sprintf( buf, "-%d", rMap.getSize(2)-p[2] ); | 290 | sprintf( buf, "-%d", rMap.getSize(2)-p[2] ); |
| 202 | strcat( fname, buf ); | 291 | strcat( fname, buf ); |
| 292 | sprintf( buf, "Floor: %d", rMap.getSize(2)-p[2] ); | ||
| 293 | strcpy( title, buf ); | ||
| 203 | for( int j = 3; j < iDims; j++ ) | 294 | for( int j = 3; j < iDims; j++ ) |
| 204 | { | 295 | { |
| 205 | sprintf( buf, "-%d", rMap.getSize(j)-p[j] ); | 296 | sprintf( buf, "-%d", rMap.getSize(j)-p[j] ); |
| 206 | strcat( fname, buf ); | 297 | strcat( fname, buf ); |
| 298 | sprintf( buf, ", %d", rMap.getSize(j)-p[j] ); | ||
| 299 | strcat( title, buf ); | ||
| 207 | } | 300 | } |
| 208 | } | 301 | } |
| 302 | else | ||
| 303 | title[0] = '\0'; | ||
| 304 | im.drawText( fnt, ox, oy-2, 0, title ); | ||
| 209 | strcat( fname, ".png"); | 305 | strcat( fname, ".png"); |
| 210 | printf("Output: %s\n", fname ); | 306 | printf("Output: %s\n", fname ); |
| 211 | 307 | ||
| 212 | png_structp png_ptr = png_create_write_struct( | 308 | im.save( fname, pal ); |
| 213 | PNG_LIBPNG_VER_STRING, NULL, NULL, NULL | ||
| 214 | ); | ||
| 215 | png_infop info_ptr = png_create_info_struct(png_ptr); | ||
| 216 | png_set_IHDR(png_ptr, info_ptr, iBufWidth, iBufHeight, | ||
| 217 | 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, | ||
| 218 | PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT | ||
| 219 | ); | ||
| 220 | png_color col[2]; | ||
| 221 | col[0].red = col[0].green = col[0].blue = 0; | ||
| 222 | col[1].red = col[1].green = col[1].blue = 255; | ||
| 223 | png_set_PLTE( png_ptr, info_ptr, col, 2); | ||
| 224 | |||
| 225 | png_set_rows( png_ptr, info_ptr, pRows ); | ||
| 226 | |||
| 227 | FILE *fp = fopen(fname, "wb"); | ||
| 228 | if( fp == NULL ) | ||
| 229 | { | ||
| 230 | printf("Error opening file!\n"); | ||
| 231 | exit( 1 ); | ||
| 232 | } | ||
| 233 | |||
| 234 | png_init_io( png_ptr, fp ); | ||
| 235 | png_write_png( png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL ); | ||
| 236 | png_destroy_write_struct( &png_ptr, &info_ptr ); | ||
| 237 | fclose( fp ); | ||
| 238 | 309 | ||
| 239 | memset( pBuf, 1, iBufSize ); | 310 | im.clear( 1 ); |
| 240 | } | 311 | } |
| 241 | } | 312 | } |
| 242 | if( iDim == iDims ) | 313 | if( iDim == iDims ) |
| @@ -260,7 +331,5 @@ void RenderPng::render() | |||
| 260 | } | 331 | } |
| 261 | // printf(buf); | 332 | // printf(buf); |
| 262 | 333 | ||
| 263 | delete[] pBuf; | ||
| 264 | delete[] pRows; | ||
| 265 | } | 334 | } |
| 266 | 335 | ||
