X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1e6feb95a79834836e88143b15d9f424ebe79621..63e02796620637b50a96d74a2264f3dea8def866:/src/common/xpmdecod.cpp diff --git a/src/common/xpmdecod.cpp b/src/common/xpmdecod.cpp index a4b8c82886..709cc6e7dc 100644 --- a/src/common/xpmdecod.cpp +++ b/src/common/xpmdecod.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: xpmdecod.cpp +// Name: src/common/xpmdecod.cpp // Purpose: wxXPMDecoder // Author: John Cristy, Vaclav Slavik // RCS-ID: $Id$ @@ -90,57 +90,61 @@ license is as follows: * in this Software without prior written authorization from GROUPE BULL. */ -#ifdef __GNUG__ -#pragma implementation "xpmdecod.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ -# pragma hdrstop + #pragma hdrstop #endif +#if wxUSE_IMAGE && wxUSE_XPM + +#include "wx/xpmdecod.h" + #ifndef WX_PRECOMP -# include "wx/defs.h" + #include "wx/intl.h" + #include "wx/log.h" + #include "wx/utils.h" + #include "wx/hashmap.h" + #include "wx/stream.h" + #include "wx/image.h" #endif - -#include "wx/stream.h" -#include "wx/image.h" -#include "wx/utils.h" -#include "wx/log.h" -#include "wx/intl.h" #include - -#include "wx/xpmdecod.h" +#include #if wxUSE_STREAMS bool wxXPMDecoder::CanRead(wxInputStream& stream) { unsigned char buf[9]; - stream.Read(buf, 9); - stream.SeekI(-9, wxFromCurrent); + if ( !stream.Read(buf, WXSIZEOF(buf)) ) + return false; + + stream.SeekI(-(wxFileOffset)WXSIZEOF(buf), wxFromCurrent); - return (memcmp(buf, "/* XPM */", 9) == 0); + return memcmp(buf, "/* XPM */", WXSIZEOF(buf)) == 0; } wxImage wxXPMDecoder::ReadFile(wxInputStream& stream) { size_t length = stream.GetSize(); - wxCHECK_MSG(length != 0, wxNullImage, wxT("Cannot read XPM from stream of unknown size")); + wxCHECK_MSG( length != 0, wxNullImage, + wxT("Cannot read XPM from stream of unknown size") ); - char *xpm_buffer = new char[length]; - char *p, *q; - size_t i; + // use a smart buffer to be sure to free memory even when we return on + // error + wxCharBuffer buffer(length); - if ( stream.Read(xpm_buffer, length).LastError() == wxSTREAM_READ_ERROR ) - return FALSE; + char *xpm_buffer = (char *)buffer.data(); + if ( stream.Read(xpm_buffer, length).GetLastError() == wxSTREAM_READ_ERROR ) + return wxNullImage; + xpm_buffer[length] = '\0'; /* * Remove comments from the file: */ + char *p, *q; for (p = xpm_buffer; *p != '\0'; p++) { if ( (*p == '"') || (*p == '\'') ) @@ -168,13 +172,16 @@ wxImage wxXPMDecoder::ReadFile(wxInputStream& stream) if ( (*q == '*') && (*(q + 1) == '/') ) break; } - strcpy(p, q + 2); + + // memmove allows overlaps (unlike strcpy): + size_t cpylen = strlen(q + 2) + 1; + memmove(p, q + 2, cpylen); } /* * Remove unquoted characters: */ - i = 0; + size_t i = 0; for (p = xpm_buffer; *p != '\0'; p++) { if ( *p != '"' ) @@ -202,7 +209,13 @@ wxImage wxXPMDecoder::ReadFile(wxInputStream& stream) lines_cnt++; } - xpm_lines = new const char*[lines_cnt]; + if ( !lines_cnt ) + { + // this doesn't really look an XPM image + return wxNullImage; + } + + xpm_lines = new const char*[lines_cnt + 1]; xpm_lines[0] = xpm_buffer; line = 1; for (p = xpm_buffer; (*p != '\0') && (line < lines_cnt); p++) @@ -215,17 +228,15 @@ wxImage wxXPMDecoder::ReadFile(wxInputStream& stream) } } + xpm_lines[lines_cnt] = NULL; + /* * Read the image: */ wxImage img = ReadData(xpm_lines); - delete[] xpm_buffer; -#ifdef __WIN16__ - delete[] (char**) xpm_lines; -#else delete[] xpm_lines; -#endif + return img; } #endif // wxUSE_STREAMS @@ -248,7 +259,7 @@ wxImage wxXPMDecoder::ReadFile(wxInputStream& stream) typedef struct { - char *name; + const char *name; wxUint32 rgb; } rgbRecord; @@ -256,261 +267,262 @@ typedef struct static rgbRecord theRGBRecords[] = { - {"AliceBlue", myRGB(240, 248, 255)}, - {"AntiqueWhite", myRGB(250, 235, 215)}, - {"Aquamarine", myRGB(50, 191, 193)}, - {"Azure", myRGB(240, 255, 255)}, - {"Beige", myRGB(245, 245, 220)}, - {"Bisque", myRGB(255, 228, 196)}, - {"Black", myRGB(0, 0, 0)}, - {"BlanchedAlmond", myRGB(255, 235, 205)}, - {"Blue", myRGB(0, 0, 255)}, - {"BlueViolet", myRGB(138, 43, 226)}, - {"Brown", myRGB(165, 42, 42)}, + {"aliceblue", myRGB(240, 248, 255)}, + {"antiquewhite", myRGB(250, 235, 215)}, + {"aquamarine", myRGB(50, 191, 193)}, + {"azure", myRGB(240, 255, 255)}, + {"beige", myRGB(245, 245, 220)}, + {"bisque", myRGB(255, 228, 196)}, + {"black", myRGB(0, 0, 0)}, + {"blanchedalmond", myRGB(255, 235, 205)}, + {"blue", myRGB(0, 0, 255)}, + {"blueviolet", myRGB(138, 43, 226)}, + {"brown", myRGB(165, 42, 42)}, {"burlywood", myRGB(222, 184, 135)}, - {"CadetBlue", myRGB(95, 146, 158)}, + {"cadetblue", myRGB(95, 146, 158)}, {"chartreuse", myRGB(127, 255, 0)}, {"chocolate", myRGB(210, 105, 30)}, - {"Coral", myRGB(255, 114, 86)}, - {"CornflowerBlue", myRGB(34, 34, 152)}, + {"coral", myRGB(255, 114, 86)}, + {"cornflowerblue", myRGB(34, 34, 152)}, {"cornsilk", myRGB(255, 248, 220)}, - {"Cyan", myRGB(0, 255, 255)}, - {"DarkGoldenrod", myRGB(184, 134, 11)}, - {"DarkGreen", myRGB(0, 86, 45)}, - {"DarkKhaki", myRGB(189, 183, 107)}, - {"DarkOliveGreen", myRGB(85, 86, 47)}, - {"DarkOrange", myRGB(255, 140, 0)}, - {"DarkOrchid", myRGB(139, 32, 139)}, - {"DarkSalmon", myRGB(233, 150, 122)}, - {"DarkSeaGreen", myRGB(143, 188, 143)}, - {"DarkSlateBlue", myRGB(56, 75, 102)}, - {"DarkSlateGray", myRGB(47, 79, 79)}, - {"DarkTurquoise", myRGB(0, 166, 166)}, - {"DarkViolet", myRGB(148, 0, 211)}, - {"DeepPink", myRGB(255, 20, 147)}, - {"DeepSkyBlue", myRGB(0, 191, 255)}, - {"DimGray", myRGB(84, 84, 84)}, - {"DodgerBlue", myRGB(30, 144, 255)}, - {"Firebrick", myRGB(142, 35, 35)}, - {"FloralWhite", myRGB(255, 250, 240)}, - {"ForestGreen", myRGB(80, 159, 105)}, + {"cyan", myRGB(0, 255, 255)}, + {"darkgoldenrod", myRGB(184, 134, 11)}, + {"darkgreen", myRGB(0, 86, 45)}, + {"darkkhaki", myRGB(189, 183, 107)}, + {"darkolivegreen", myRGB(85, 86, 47)}, + {"darkorange", myRGB(255, 140, 0)}, + {"darkorchid", myRGB(139, 32, 139)}, + {"darksalmon", myRGB(233, 150, 122)}, + {"darkseagreen", myRGB(143, 188, 143)}, + {"darkslateblue", myRGB(56, 75, 102)}, + {"darkslategray", myRGB(47, 79, 79)}, + {"darkturquoise", myRGB(0, 166, 166)}, + {"darkviolet", myRGB(148, 0, 211)}, + {"deeppink", myRGB(255, 20, 147)}, + {"deepskyblue", myRGB(0, 191, 255)}, + {"dimgray", myRGB(84, 84, 84)}, + {"dodgerblue", myRGB(30, 144, 255)}, + {"firebrick", myRGB(142, 35, 35)}, + {"floralwhite", myRGB(255, 250, 240)}, + {"forestgreen", myRGB(80, 159, 105)}, {"gainsboro", myRGB(220, 220, 220)}, - {"GhostWhite", myRGB(248, 248, 255)}, - {"Gold", myRGB(218, 170, 0)}, - {"Goldenrod", myRGB(239, 223, 132)}, - {"Gray", myRGB(126, 126, 126)}, - {"Gray0", myRGB(0, 0, 0)}, - {"Gray1", myRGB(3, 3, 3)}, - {"Gray10", myRGB(26, 26, 26)}, - {"Gray100", myRGB(255, 255, 255)}, - {"Gray11", myRGB(28, 28, 28)}, - {"Gray12", myRGB(31, 31, 31)}, - {"Gray13", myRGB(33, 33, 33)}, - {"Gray14", myRGB(36, 36, 36)}, - {"Gray15", myRGB(38, 38, 38)}, - {"Gray16", myRGB(41, 41, 41)}, - {"Gray17", myRGB(43, 43, 43)}, - {"Gray18", myRGB(46, 46, 46)}, - {"Gray19", myRGB(48, 48, 48)}, - {"Gray2", myRGB(5, 5, 5)}, - {"Gray20", myRGB(51, 51, 51)}, - {"Gray21", myRGB(54, 54, 54)}, - {"Gray22", myRGB(56, 56, 56)}, - {"Gray23", myRGB(59, 59, 59)}, - {"Gray24", myRGB(61, 61, 61)}, - {"Gray25", myRGB(64, 64, 64)}, - {"Gray26", myRGB(66, 66, 66)}, - {"Gray27", myRGB(69, 69, 69)}, - {"Gray28", myRGB(71, 71, 71)}, - {"Gray29", myRGB(74, 74, 74)}, - {"Gray3", myRGB(8, 8, 8)}, - {"Gray30", myRGB(77, 77, 77)}, - {"Gray31", myRGB(79, 79, 79)}, - {"Gray32", myRGB(82, 82, 82)}, - {"Gray33", myRGB(84, 84, 84)}, - {"Gray34", myRGB(87, 87, 87)}, - {"Gray35", myRGB(89, 89, 89)}, - {"Gray36", myRGB(92, 92, 92)}, - {"Gray37", myRGB(94, 94, 94)}, - {"Gray38", myRGB(97, 97, 97)}, - {"Gray39", myRGB(99, 99, 99)}, - {"Gray4", myRGB(10, 10, 10)}, - {"Gray40", myRGB(102, 102, 102)}, - {"Gray41", myRGB(105, 105, 105)}, - {"Gray42", myRGB(107, 107, 107)}, - {"Gray43", myRGB(110, 110, 110)}, - {"Gray44", myRGB(112, 112, 112)}, - {"Gray45", myRGB(115, 115, 115)}, - {"Gray46", myRGB(117, 117, 117)}, - {"Gray47", myRGB(120, 120, 120)}, - {"Gray48", myRGB(122, 122, 122)}, - {"Gray49", myRGB(125, 125, 125)}, - {"Gray5", myRGB(13, 13, 13)}, - {"Gray50", myRGB(127, 127, 127)}, - {"Gray51", myRGB(130, 130, 130)}, - {"Gray52", myRGB(133, 133, 133)}, - {"Gray53", myRGB(135, 135, 135)}, - {"Gray54", myRGB(138, 138, 138)}, - {"Gray55", myRGB(140, 140, 140)}, - {"Gray56", myRGB(143, 143, 143)}, - {"Gray57", myRGB(145, 145, 145)}, - {"Gray58", myRGB(148, 148, 148)}, - {"Gray59", myRGB(150, 150, 150)}, - {"Gray6", myRGB(15, 15, 15)}, - {"Gray60", myRGB(153, 153, 153)}, - {"Gray61", myRGB(156, 156, 156)}, - {"Gray62", myRGB(158, 158, 158)}, - {"Gray63", myRGB(161, 161, 161)}, - {"Gray64", myRGB(163, 163, 163)}, - {"Gray65", myRGB(166, 166, 166)}, - {"Gray66", myRGB(168, 168, 168)}, - {"Gray67", myRGB(171, 171, 171)}, - {"Gray68", myRGB(173, 173, 173)}, - {"Gray69", myRGB(176, 176, 176)}, - {"Gray7", myRGB(18, 18, 18)}, - {"Gray70", myRGB(179, 179, 179)}, - {"Gray71", myRGB(181, 181, 181)}, - {"Gray72", myRGB(184, 184, 184)}, - {"Gray73", myRGB(186, 186, 186)}, - {"Gray74", myRGB(189, 189, 189)}, - {"Gray75", myRGB(191, 191, 191)}, - {"Gray76", myRGB(194, 194, 194)}, - {"Gray77", myRGB(196, 196, 196)}, - {"Gray78", myRGB(199, 199, 199)}, - {"Gray79", myRGB(201, 201, 201)}, - {"Gray8", myRGB(20, 20, 20)}, - {"Gray80", myRGB(204, 204, 204)}, - {"Gray81", myRGB(207, 207, 207)}, - {"Gray82", myRGB(209, 209, 209)}, - {"Gray83", myRGB(212, 212, 212)}, - {"Gray84", myRGB(214, 214, 214)}, - {"Gray85", myRGB(217, 217, 217)}, - {"Gray86", myRGB(219, 219, 219)}, - {"Gray87", myRGB(222, 222, 222)}, - {"Gray88", myRGB(224, 224, 224)}, - {"Gray89", myRGB(227, 227, 227)}, - {"Gray9", myRGB(23, 23, 23)}, - {"Gray90", myRGB(229, 229, 229)}, - {"Gray91", myRGB(232, 232, 232)}, - {"Gray92", myRGB(235, 235, 235)}, - {"Gray93", myRGB(237, 237, 237)}, - {"Gray94", myRGB(240, 240, 240)}, - {"Gray95", myRGB(242, 242, 242)}, - {"Gray96", myRGB(245, 245, 245)}, - {"Gray97", myRGB(247, 247, 247)}, - {"Gray98", myRGB(250, 250, 250)}, - {"Gray99", myRGB(252, 252, 252)}, - {"Green", myRGB(0, 255, 0)}, - {"GreenYellow", myRGB(173, 255, 47)}, + {"ghostwhite", myRGB(248, 248, 255)}, + {"gold", myRGB(218, 170, 0)}, + {"goldenrod", myRGB(239, 223, 132)}, + {"gray", myRGB(126, 126, 126)}, + {"gray0", myRGB(0, 0, 0)}, + {"gray1", myRGB(3, 3, 3)}, + {"gray10", myRGB(26, 26, 26)}, + {"gray100", myRGB(255, 255, 255)}, + {"gray11", myRGB(28, 28, 28)}, + {"gray12", myRGB(31, 31, 31)}, + {"gray13", myRGB(33, 33, 33)}, + {"gray14", myRGB(36, 36, 36)}, + {"gray15", myRGB(38, 38, 38)}, + {"gray16", myRGB(41, 41, 41)}, + {"gray17", myRGB(43, 43, 43)}, + {"gray18", myRGB(46, 46, 46)}, + {"gray19", myRGB(48, 48, 48)}, + {"gray2", myRGB(5, 5, 5)}, + {"gray20", myRGB(51, 51, 51)}, + {"gray21", myRGB(54, 54, 54)}, + {"gray22", myRGB(56, 56, 56)}, + {"gray23", myRGB(59, 59, 59)}, + {"gray24", myRGB(61, 61, 61)}, + {"gray25", myRGB(64, 64, 64)}, + {"gray26", myRGB(66, 66, 66)}, + {"gray27", myRGB(69, 69, 69)}, + {"gray28", myRGB(71, 71, 71)}, + {"gray29", myRGB(74, 74, 74)}, + {"gray3", myRGB(8, 8, 8)}, + {"gray30", myRGB(77, 77, 77)}, + {"gray31", myRGB(79, 79, 79)}, + {"gray32", myRGB(82, 82, 82)}, + {"gray33", myRGB(84, 84, 84)}, + {"gray34", myRGB(87, 87, 87)}, + {"gray35", myRGB(89, 89, 89)}, + {"gray36", myRGB(92, 92, 92)}, + {"gray37", myRGB(94, 94, 94)}, + {"gray38", myRGB(97, 97, 97)}, + {"gray39", myRGB(99, 99, 99)}, + {"gray4", myRGB(10, 10, 10)}, + {"gray40", myRGB(102, 102, 102)}, + {"gray41", myRGB(105, 105, 105)}, + {"gray42", myRGB(107, 107, 107)}, + {"gray43", myRGB(110, 110, 110)}, + {"gray44", myRGB(112, 112, 112)}, + {"gray45", myRGB(115, 115, 115)}, + {"gray46", myRGB(117, 117, 117)}, + {"gray47", myRGB(120, 120, 120)}, + {"gray48", myRGB(122, 122, 122)}, + {"gray49", myRGB(125, 125, 125)}, + {"gray5", myRGB(13, 13, 13)}, + {"gray50", myRGB(127, 127, 127)}, + {"gray51", myRGB(130, 130, 130)}, + {"gray52", myRGB(133, 133, 133)}, + {"gray53", myRGB(135, 135, 135)}, + {"gray54", myRGB(138, 138, 138)}, + {"gray55", myRGB(140, 140, 140)}, + {"gray56", myRGB(143, 143, 143)}, + {"gray57", myRGB(145, 145, 145)}, + {"gray58", myRGB(148, 148, 148)}, + {"gray59", myRGB(150, 150, 150)}, + {"gray6", myRGB(15, 15, 15)}, + {"gray60", myRGB(153, 153, 153)}, + {"gray61", myRGB(156, 156, 156)}, + {"gray62", myRGB(158, 158, 158)}, + {"gray63", myRGB(161, 161, 161)}, + {"gray64", myRGB(163, 163, 163)}, + {"gray65", myRGB(166, 166, 166)}, + {"gray66", myRGB(168, 168, 168)}, + {"gray67", myRGB(171, 171, 171)}, + {"gray68", myRGB(173, 173, 173)}, + {"gray69", myRGB(176, 176, 176)}, + {"gray7", myRGB(18, 18, 18)}, + {"gray70", myRGB(179, 179, 179)}, + {"gray71", myRGB(181, 181, 181)}, + {"gray72", myRGB(184, 184, 184)}, + {"gray73", myRGB(186, 186, 186)}, + {"gray74", myRGB(189, 189, 189)}, + {"gray75", myRGB(191, 191, 191)}, + {"gray76", myRGB(194, 194, 194)}, + {"gray77", myRGB(196, 196, 196)}, + {"gray78", myRGB(199, 199, 199)}, + {"gray79", myRGB(201, 201, 201)}, + {"gray8", myRGB(20, 20, 20)}, + {"gray80", myRGB(204, 204, 204)}, + {"gray81", myRGB(207, 207, 207)}, + {"gray82", myRGB(209, 209, 209)}, + {"gray83", myRGB(212, 212, 212)}, + {"gray84", myRGB(214, 214, 214)}, + {"gray85", myRGB(217, 217, 217)}, + {"gray86", myRGB(219, 219, 219)}, + {"gray87", myRGB(222, 222, 222)}, + {"gray88", myRGB(224, 224, 224)}, + {"gray89", myRGB(227, 227, 227)}, + {"gray9", myRGB(23, 23, 23)}, + {"gray90", myRGB(229, 229, 229)}, + {"gray91", myRGB(232, 232, 232)}, + {"gray92", myRGB(235, 235, 235)}, + {"gray93", myRGB(237, 237, 237)}, + {"gray94", myRGB(240, 240, 240)}, + {"gray95", myRGB(242, 242, 242)}, + {"gray96", myRGB(245, 245, 245)}, + {"gray97", myRGB(247, 247, 247)}, + {"gray98", myRGB(250, 250, 250)}, + {"gray99", myRGB(252, 252, 252)}, + {"green", myRGB(0, 255, 0)}, + {"greenyellow", myRGB(173, 255, 47)}, {"honeydew", myRGB(240, 255, 240)}, - {"HotPink", myRGB(255, 105, 180)}, - {"IndianRed", myRGB(107, 57, 57)}, + {"hotpink", myRGB(255, 105, 180)}, + {"indianred", myRGB(107, 57, 57)}, {"ivory", myRGB(255, 255, 240)}, - {"Khaki", myRGB(179, 179, 126)}, + {"khaki", myRGB(179, 179, 126)}, {"lavender", myRGB(230, 230, 250)}, - {"LavenderBlush", myRGB(255, 240, 245)}, - {"LawnGreen", myRGB(124, 252, 0)}, - {"LemonChiffon", myRGB(255, 250, 205)}, - {"LightBlue", myRGB(176, 226, 255)}, - {"LightCoral", myRGB(240, 128, 128)}, - {"LightCyan", myRGB(224, 255, 255)}, - {"LightGoldenrod", myRGB(238, 221, 130)}, - {"LightGoldenrodYellow", myRGB(250, 250, 210)}, - {"LightGray", myRGB(168, 168, 168)}, - {"LightPink", myRGB(255, 182, 193)}, - {"LightSalmon", myRGB(255, 160, 122)}, - {"LightSeaGreen", myRGB(32, 178, 170)}, - {"LightSkyBlue", myRGB(135, 206, 250)}, - {"LightSlateBlue", myRGB(132, 112, 255)}, - {"LightSlateGray", myRGB(119, 136, 153)}, - {"LightSteelBlue", myRGB(124, 152, 211)}, - {"LightYellow", myRGB(255, 255, 224)}, - {"LimeGreen", myRGB(0, 175, 20)}, + {"lavenderblush", myRGB(255, 240, 245)}, + {"lawngreen", myRGB(124, 252, 0)}, + {"lemonchiffon", myRGB(255, 250, 205)}, + {"lightblue", myRGB(176, 226, 255)}, + {"lightcoral", myRGB(240, 128, 128)}, + {"lightcyan", myRGB(224, 255, 255)}, + {"lightgoldenrod", myRGB(238, 221, 130)}, + {"lightgoldenrodyellow", myRGB(250, 250, 210)}, + {"lightgray", myRGB(168, 168, 168)}, + {"lightpink", myRGB(255, 182, 193)}, + {"lightsalmon", myRGB(255, 160, 122)}, + {"lightseagreen", myRGB(32, 178, 170)}, + {"lightskyblue", myRGB(135, 206, 250)}, + {"lightslateblue", myRGB(132, 112, 255)}, + {"lightslategray", myRGB(119, 136, 153)}, + {"lightsteelblue", myRGB(124, 152, 211)}, + {"lightyellow", myRGB(255, 255, 224)}, + {"limegreen", myRGB(0, 175, 20)}, {"linen", myRGB(250, 240, 230)}, - {"Magenta", myRGB(255, 0, 255)}, - {"Maroon", myRGB(143, 0, 82)}, - {"MediumAquamarine", myRGB(0, 147, 143)}, - {"MediumBlue", myRGB(50, 50, 204)}, - {"MediumForestGreen", myRGB(50, 129, 75)}, - {"MediumGoldenrod", myRGB(209, 193, 102)}, - {"MediumOrchid", myRGB(189, 82, 189)}, - {"MediumPurple", myRGB(147, 112, 219)}, - {"MediumSeaGreen", myRGB(52, 119, 102)}, - {"MediumSlateBlue", myRGB(106, 106, 141)}, - {"MediumSpringGreen", myRGB(35, 142, 35)}, - {"MediumTurquoise", myRGB(0, 210, 210)}, - {"MediumVioletRed", myRGB(213, 32, 121)}, - {"MidnightBlue", myRGB(47, 47, 100)}, - {"MintCream", myRGB(245, 255, 250)}, - {"MistyRose", myRGB(255, 228, 225)}, + {"magenta", myRGB(255, 0, 255)}, + {"maroon", myRGB(143, 0, 82)}, + {"mediumaquamarine", myRGB(0, 147, 143)}, + {"mediumblue", myRGB(50, 50, 204)}, + {"mediumforestgreen", myRGB(50, 129, 75)}, + {"mediumgoldenrod", myRGB(209, 193, 102)}, + {"mediumorchid", myRGB(189, 82, 189)}, + {"mediumpurple", myRGB(147, 112, 219)}, + {"mediumseagreen", myRGB(52, 119, 102)}, + {"mediumslateblue", myRGB(106, 106, 141)}, + {"mediumspringgreen", myRGB(35, 142, 35)}, + {"mediumturquoise", myRGB(0, 210, 210)}, + {"mediumvioletred", myRGB(213, 32, 121)}, + {"midnightblue", myRGB(47, 47, 100)}, + {"mintcream", myRGB(245, 255, 250)}, + {"mistyrose", myRGB(255, 228, 225)}, {"moccasin", myRGB(255, 228, 181)}, - {"NavajoWhite", myRGB(255, 222, 173)}, - {"Navy", myRGB(35, 35, 117)}, - {"NavyBlue", myRGB(35, 35, 117)}, - {"OldLace", myRGB(253, 245, 230)}, - {"OliveDrab", myRGB(107, 142, 35)}, - {"Orange", myRGB(255, 135, 0)}, - {"OrangeRed", myRGB(255, 69, 0)}, - {"Orchid", myRGB(239, 132, 239)}, - {"PaleGoldenrod", myRGB(238, 232, 170)}, - {"PaleGreen", myRGB(115, 222, 120)}, - {"PaleTurquoise", myRGB(175, 238, 238)}, - {"PaleVioletRed", myRGB(219, 112, 147)}, - {"PapayaWhip", myRGB(255, 239, 213)}, - {"PeachPuff", myRGB(255, 218, 185)}, + {"navajowhite", myRGB(255, 222, 173)}, + {"navy", myRGB(35, 35, 117)}, + {"navyblue", myRGB(35, 35, 117)}, + {"oldlace", myRGB(253, 245, 230)}, + {"olivedrab", myRGB(107, 142, 35)}, + {"orange", myRGB(255, 135, 0)}, + {"orangered", myRGB(255, 69, 0)}, + {"orchid", myRGB(239, 132, 239)}, + {"palegoldenrod", myRGB(238, 232, 170)}, + {"palegreen", myRGB(115, 222, 120)}, + {"paleturquoise", myRGB(175, 238, 238)}, + {"palevioletred", myRGB(219, 112, 147)}, + {"papayawhip", myRGB(255, 239, 213)}, + {"peachpuff", myRGB(255, 218, 185)}, {"peru", myRGB(205, 133, 63)}, - {"Pink", myRGB(255, 181, 197)}, - {"Plum", myRGB(197, 72, 155)}, - {"PowderBlue", myRGB(176, 224, 230)}, + {"pink", myRGB(255, 181, 197)}, + {"plum", myRGB(197, 72, 155)}, + {"powderblue", myRGB(176, 224, 230)}, {"purple", myRGB(160, 32, 240)}, - {"Red", myRGB(255, 0, 0)}, - {"RosyBrown", myRGB(188, 143, 143)}, - {"RoyalBlue", myRGB(65, 105, 225)}, - {"SaddleBrown", myRGB(139, 69, 19)}, - {"Salmon", myRGB(233, 150, 122)}, - {"SandyBrown", myRGB(244, 164, 96)}, - {"SeaGreen", myRGB(82, 149, 132)}, + {"red", myRGB(255, 0, 0)}, + {"rosybrown", myRGB(188, 143, 143)}, + {"royalblue", myRGB(65, 105, 225)}, + {"saddlebrown", myRGB(139, 69, 19)}, + {"salmon", myRGB(233, 150, 122)}, + {"sandybrown", myRGB(244, 164, 96)}, + {"seagreen", myRGB(82, 149, 132)}, {"seashell", myRGB(255, 245, 238)}, - {"Sienna", myRGB(150, 82, 45)}, - {"SkyBlue", myRGB(114, 159, 255)}, - {"SlateBlue", myRGB(126, 136, 171)}, - {"SlateGray", myRGB(112, 128, 144)}, + {"sienna", myRGB(150, 82, 45)}, + {"silver", myRGB(192, 192, 192)}, + {"skyblue", myRGB(114, 159, 255)}, + {"slateblue", myRGB(126, 136, 171)}, + {"slategray", myRGB(112, 128, 144)}, {"snow", myRGB(255, 250, 250)}, - {"SpringGreen", myRGB(65, 172, 65)}, - {"SteelBlue", myRGB(84, 112, 170)}, - {"Tan", myRGB(222, 184, 135)}, - {"Thistle", myRGB(216, 191, 216)}, + {"springgreen", myRGB(65, 172, 65)}, + {"steelblue", myRGB(84, 112, 170)}, + {"tan", myRGB(222, 184, 135)}, + {"thistle", myRGB(216, 191, 216)}, {"tomato", myRGB(255, 99, 71)}, - {"Transparent", myRGB(0, 0, 1)}, - {"Turquoise", myRGB(25, 204, 223)}, - {"Violet", myRGB(156, 62, 206)}, - {"VioletRed", myRGB(243, 62, 150)}, - {"Wheat", myRGB(245, 222, 179)}, - {"White", myRGB(255, 255, 255)}, - {"WhiteSmoke", myRGB(245, 245, 245)}, - {"Yellow", myRGB(255, 255, 0)}, - {"YellowGreen", myRGB(50, 216, 56)}, + {"transparent", myRGB(0, 0, 1)}, + {"turquoise", myRGB(25, 204, 223)}, + {"violet", myRGB(156, 62, 206)}, + {"violetred", myRGB(243, 62, 150)}, + {"wheat", myRGB(245, 222, 179)}, + {"white", myRGB(255, 255, 255)}, + {"whitesmoke", myRGB(245, 245, 245)}, + {"yellow", myRGB(255, 255, 0)}, + {"yellowgreen", myRGB(50, 216, 56)}, {NULL, myRGB(0, 0, 0)} }; -static int numTheRGBRecords = 234; +static int numTheRGBRecords = 235; static unsigned char ParseHexadecimal(char digit1, char digit2) { unsigned char i1, i2; if (digit1 >= 'a') - i1 = digit1 - 'a' + 0x0A; + i1 = (unsigned char)(digit1 - 'a' + 0x0A); else if (digit1 >= 'A') - i1 = digit1 - 'A' + 0x0A; + i1 = (unsigned char)(digit1 - 'A' + 0x0A); else - i1 = digit1 - '0'; + i1 = (unsigned char)(digit1 - '0'); if (digit2 >= 'a') - i2 = digit2 - 'a' + 0x0A; + i2 = (unsigned char)(digit2 - 'a' + 0x0A); else if (digit2 >= 'A') - i2 = digit2 - 'A' + 0x0A; + i2 = (unsigned char)(digit2 - 'A' + 0x0A); else - i2 = digit2 - '0'; - return (0x10 * i1 + i2); + i2 = (unsigned char)(digit2 - '0'); + return (unsigned char)(0x10 * i1 + i2); } static bool GetRGBFromName(const char *inname, bool *isNone, @@ -522,17 +534,19 @@ static bool GetRGBFromName(const char *inname, bool *isNone, char *name; char *grey, *p; - // #rrggbb are not in database, we parse them directly - if ( *inname == '#' && strlen(inname) == 7 ) + // Neither #rrggbb nor #rrrrggggbbbb are in database, we parse them directly + size_t inname_len = strlen(inname); + if ( *inname == '#' && (inname_len == 7 || inname_len == 13)) { + size_t ofs = (inname_len == 7) ? 2 : 4; *r = ParseHexadecimal(inname[1], inname[2]); - *g = ParseHexadecimal(inname[3], inname[4]); - *b = ParseHexadecimal(inname[5], inname[6]); - *isNone = FALSE; - return TRUE; + *g = ParseHexadecimal(inname[1*ofs+1], inname[1*ofs+2]); + *b = ParseHexadecimal(inname[2*ofs+1], inname[2*ofs+2]); + *isNone = false; + return true; } - name = strdup(inname); + name = wxStrdupA(inname); // theRGBRecords[] has no names with spaces, and no grey, but a // lot of gray... @@ -550,7 +564,7 @@ static bool GetRGBFromName(const char *inname, bool *isNone, p = name; while (*p) { - *p = tolower(*p); + *p = (char)tolower(*p); p++; } @@ -563,12 +577,12 @@ static bool GetRGBFromName(const char *inname, bool *isNone, bool found; if ( strcmp(name, "none") == 0 ) { - *isNone = TRUE; - found = TRUE; + *isNone = true; + found = true; } else // not "None" { - found = FALSE; + found = false; // binary search: left = 0; @@ -583,8 +597,8 @@ static bool GetRGBFromName(const char *inname, bool *isNone, *r = (unsigned char)((rgbVal >> 16) & 0xFF); *g = (unsigned char)((rgbVal >> 8) & 0xFF); *b = (unsigned char)((rgbVal) & 0xFF); - *isNone = FALSE; - found = TRUE; + *isNone = false; + found = true; break; } else if ( cmp < 0 ) @@ -635,14 +649,17 @@ static const char *ParseColor(const char *data) return NULL; } -class wxXPMColourMapData : public wxObject +struct wxXPMColourMapData { - public: - unsigned char R,G,B; + wxXPMColourMapData() { R = G = B = 0; } + unsigned char R,G,B; }; +WX_DECLARE_STRING_HASH_MAP(wxXPMColourMapData, wxXPMColourMap); -wxImage wxXPMDecoder::ReadData(const char **xpm_data) +wxImage wxXPMDecoder::ReadData(const char* const* xpm_data) { + wxCHECK_MSG(xpm_data, wxNullImage, wxT("NULL XPM data") ); + wxImage img; int count; unsigned width, height, colors_cnt, chars_per_pixel; @@ -650,18 +667,19 @@ wxImage wxXPMDecoder::ReadData(const char **xpm_data) wxChar key[64]; const char *clr_def; bool hasMask; - wxXPMColourMapData *clr_data; - wxHashTable clr_tbl(wxKEY_STRING); + wxXPMColourMap clr_tbl; + wxXPMColourMap::iterator it; + wxString maskKey; /* * Read hints and initialize structures: */ - + count = sscanf(xpm_data[0], "%u %u %u %u", &width, &height, &colors_cnt, &chars_per_pixel); if ( count != 4 || width * height * colors_cnt == 0 ) { - wxLogError(_T("XPM: Not XPM data!")); + wxLogError(_("XPM: incorrect header format!")); return wxNullImage; } @@ -670,56 +688,79 @@ wxImage wxXPMDecoder::ReadData(const char **xpm_data) // 8bit RGB... wxCHECK_MSG(chars_per_pixel < 64, wxNullImage, wxT("XPM colormaps this large not supported.")); - img.Create(width, height); - if ( !img.Ok() ) return img; + if ( !img.Create(width, height) ) + return wxNullImage; - img.SetMask(FALSE); + img.SetMask(false); key[chars_per_pixel] = wxT('\0'); - hasMask = FALSE; - clr_tbl.DeleteContents(TRUE); + hasMask = false; /* * Create colour map: */ + wxXPMColourMapData clr_data; for (i = 0; i < colors_cnt; i++) { + const char *xmpColLine = xpm_data[1 + i]; + + // we must have at least " x y" after the colour index, hence +5 + if ( !xmpColLine || strlen(xmpColLine) < chars_per_pixel + 5 ) + { + wxLogError(_("XPM: incorrect colour description in line %d"), + (int)(1 + i)); + return wxNullImage; + } + for (i_key = 0; i_key < chars_per_pixel; i_key++) - key[i_key] = (wxChar)xpm_data[1 + i][i_key]; - clr_def = ParseColor(xpm_data[1 + i]); - clr_data = new wxXPMColourMapData; + key[i_key] = (wxChar)xmpColLine[i_key]; + clr_def = ParseColor(xmpColLine + chars_per_pixel); if ( clr_def == NULL ) { - wxLogError(_("XPM: malformed colour definition '%s'!"), xpm_data[1+i]); - clr_data->R = 255, clr_data->G = 0, clr_data->B = 255; + wxLogError(_("XPM: malformed colour definition '%s' at line %d!"), + xmpColLine, (int)(1 + i)); + return wxNullImage; } - else + + bool isNone = false; + if ( !GetRGBFromName(clr_def, &isNone, + &clr_data.R, &clr_data.G, &clr_data.B) ) { - bool isNone; - if ( !GetRGBFromName(clr_def, &isNone, - &clr_data->R, &clr_data->G, &clr_data->B) ) - { - wxLogError(_("XPM: malformed colour definition '%s'!"), xpm_data[1+i]); - clr_data->R = 255, clr_data->G = 0, clr_data->B = 255; - } - else + wxLogError(_("XPM: malformed colour definition '%s' at line %d!"), + xmpColLine, (int)(1 + i)); + return wxNullImage; + } + + if ( isNone ) + { + img.SetMask(true); + img.SetMaskColour(255, 0, 255); + clr_data.R = + clr_data.B = 255; + clr_data.G = 0; + hasMask = true; + maskKey = key; + } + + clr_tbl[key] = clr_data; + } + + /* + * Modify colour entries with RGB = (255,0,255) to (255,0,254) if + * mask colour is present (so that existing pixels with (255,0,255) + * magenta colour are not incorrectly made transparent): + */ + if (hasMask) + { + for (it = clr_tbl.begin(); it != clr_tbl.end(); ++it) + { + if (it->second.R == 255 && it->second.G == 0 && + it->second.B == 255 && + it->first != maskKey) { - if ( isNone ) - { - img.SetMask(TRUE); - img.SetMaskColour(255, 0, 255); - hasMask = TRUE; - clr_data->R = 255, clr_data->G = 0, clr_data->B = 255; - } - else - { - if ( hasMask && clr_data->R == 255 && - clr_data->G == 0 && clr_data->B == 255 ) - clr_data->B = 254; - } + it->second.B = 254; } } - clr_tbl.Put(key, clr_data); } /* @@ -727,23 +768,42 @@ wxImage wxXPMDecoder::ReadData(const char **xpm_data) */ unsigned char *img_data = img.GetData(); + wxXPMColourMap::iterator entry; + wxXPMColourMap::iterator end = clr_tbl.end(); + for (j = 0; j < height; j++) { for (i = 0; i < width; i++, img_data += 3) { + const char *xpmImgLine = xpm_data[1 + colors_cnt + j]; + if ( !xpmImgLine || strlen(xpmImgLine) < width*chars_per_pixel ) + { + wxLogError(_("XPM: truncated image data at line %d!"), + (int)(1 + colors_cnt + j)); + return wxNullImage; + } + for (i_key = 0; i_key < chars_per_pixel; i_key++) - key[i_key] = (wxChar)xpm_data[1 + colors_cnt + j] - [chars_per_pixel * i + i_key]; - clr_data = (wxXPMColourMapData*) clr_tbl.Get(key); - if ( clr_data == NULL ) + { + key[i_key] = (wxChar)xpmImgLine[chars_per_pixel * i + i_key]; + } + + entry = clr_tbl.find(key); + if ( entry == end ) { wxLogError(_("XPM: Malformed pixel data!")); + + // better return right now as otherwise we risk to flood the + // user with error messages as something seems to be seriously + // wrong with the file and so we could give this message for + // each remaining pixel if we don't bail out + return wxNullImage; } else { - img_data[0] = clr_data->R; - img_data[1] = clr_data->G; - img_data[2] = clr_data->B; + img_data[0] = entry->second.R; + img_data[1] = entry->second.G; + img_data[2] = entry->second.B; } } } @@ -751,4 +811,4 @@ wxImage wxXPMDecoder::ReadData(const char **xpm_data) return img; } - +#endif // wxUSE_IMAGE && wxUSE_XPM