diff options
| author | nyamatongwe <unknown> | 2003-01-10 11:06:02 +0000 | 
|---|---|---|
| committer | nyamatongwe <unknown> | 2003-01-10 11:06:02 +0000 | 
| commit | 265b37457926befea52ffc34a35b9aea510f4887 (patch) | |
| tree | a8c176637bf02315069c6d91835efd610ece5664 /src | |
| parent | 63ed30c73860930738658fa7445cb2bb215f5c43 (diff) | |
| download | scintilla-mirror-265b37457926befea52ffc34a35b9aea510f4887.tar.gz | |
Initial version.
Diffstat (limited to 'src')
| -rw-r--r-- | src/XPM.cxx | 297 | ||||
| -rw-r--r-- | src/XPM.h | 67 | 
2 files changed, 364 insertions, 0 deletions
| diff --git a/src/XPM.cxx b/src/XPM.cxx new file mode 100644 index 000000000..5758b7810 --- /dev/null +++ b/src/XPM.cxx @@ -0,0 +1,297 @@ +// Scintilla source code edit control +/** @file XPM.cxx + ** Define a class that holds data in the X Pixmap (XPM) format, + **/ +// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <string.h> +#include <stdlib.h> + +#include "Platform.h" + +#include "XPM.h" + +static const char *NextField(const char *s) { +	while (*s && *s != ' ') { +		s++; +	} +	while (*s && *s == ' ') { +		s++; +	} +	return s; +} + +// Data lines in XPM can be terminated either with NUL or " +static size_t MeasureLength(const char *s) { +	size_t i = 0; +	while (s[i] && (s[i] != '\"')) +		i++; +	return i; +} + +ColourAllocated XPM::ColourFromCode(int ch) { +	return colourCodeTable[ch]->allocated; +#ifdef SLOW +	for (int i=0;i<nColours;i++) { +		if (codes[i] == ch) { +			return colours[i].allocated; +		} +	} +	return colours[0].allocated; +#endif +} + +void XPM::FillRun(Surface *surface, int code, int startX, int y, int x) { +	if ((code != codeTransparent) && (startX != x)) { +		PRectangle rc(startX, y, x, y+1); +		surface->FillRectangle(rc, ColourFromCode(code)); +	} +} + +XPM::XPM(const char *textForm) :  +	data(0),	codes(0), colours(0), lines(0) { +	Init(textForm); +} + +XPM::XPM(const char * const *linesForm) : +	data(0),	codes(0), colours(0), lines(0) { +	Init(linesForm); +} + +XPM::~XPM() { +	Clear(); +} + +void XPM::Init(const char *textForm) { +	Clear(); +	// Test done is two parts to avoid possibility of overstepping the memory +	// if memcmp implemented strangely. Must be 4 bytes at least at destination. +	if ((0 == memcmp(textForm, "/* X", 4)) && (0 == memcmp(textForm, "/* XPM */", 9))) { +		// Build the lines form out of the text form +		const char **linesForm = LinesFormFromTextForm(textForm); +		Init(linesForm); +		delete []linesForm; +	} else { +		// It is really in line form +		Init(reinterpret_cast<const char * const *>(textForm)); +	} +} + +void XPM::Init(const char * const *linesForm) { +	Clear(); +	height = 1; +	width = 1; +	nColours = 1; +	data = NULL; +	codeTransparent = ' '; +	codes = NULL; +	colours = NULL; +	lines = NULL; +	if (!linesForm) +		return; + +	const char *line0 = linesForm[0]; +	width = atoi(line0); +	line0 = NextField(line0); +	height = atoi(line0); +	line0 = NextField(line0); +	nColours = atoi(line0); +	codes = new char[nColours]; +	colours = new ColourPair[nColours]; + +	int strings = 1+height+nColours; +	lines = new char *[strings]; +	int allocation = 0; +	for (int i=0; i<strings; i++) { +		allocation += MeasureLength(linesForm[i]) + 1; +	} +	data = new char[allocation]; +	char *nextBit = data; +	for (int j=0; j<strings; j++) { +		lines[j] = nextBit; +		size_t len = MeasureLength(linesForm[j]); +		memcpy(nextBit, linesForm[j], len); +		nextBit += len; +		*nextBit++ = '\0'; +	} + +	for (int code=0;code<256; code++) { +		colourCodeTable[code] = 0; +	} + +	for (int c=0; c<nColours; c++) { +		const char *colourDef = linesForm[c+1]; +		codes[c] = colourDef[0]; +		colourDef += 4; +		if (*colourDef == '#') { +			colours[c].desired.Set(colourDef); +		} else { +			colours[c].desired = ColourDesired(0xff, 0xff, 0xff); +			codeTransparent = codes[c]; +		} +		colourCodeTable[static_cast<unsigned char>(codes[c])] = &(colours[c]); +	} +} + +void XPM::Clear() { +	delete []data; +	data = 0; +	delete []codes; +	codes = 0; +	delete []colours; +	colours = 0; +	delete []lines; +	lines = 0; +} + +void XPM::RefreshColourPalette(Palette &pal, bool want) { +	if (!data || !codes || !colours || !lines) { +		return; +	} +	for (int i=0;i<nColours;i++) { +		pal.WantFind(colours[i], want); +	} +} + +void XPM::CopyDesiredColours() { +	if (!data || !codes || !colours || !lines) { +		return; +	} +	for (int i=0;i<nColours;i++) { +		colours[i].Copy(); +	} +} + +void XPM::Draw(Surface *surface, PRectangle &rc) { +	if (!data || !codes || !colours || !lines) { +		return; +	} +	// Centre the pixmap +	int startY = rc.top + (rc.Height() - height) / 2; +	int startX = rc.left + (rc.Width() - width) / 2; +	for (int y=0;y<height;y++) { +		int prevCode = 0; +		int xStartRun = 0; +		for (int x=0; x<width; x++) { +			int code = lines[y+nColours+1][x]; +			if (code != prevCode) { +				FillRun(surface, prevCode, startX + xStartRun, startY + y, startX + x); +				xStartRun = x; +				prevCode = code; +			} +		} +		FillRun(surface, prevCode, startX + xStartRun, startY + y, startX + width); +	} +} + +const char **XPM::LinesFormFromTextForm(const char *textForm) { +	// Build the lines form out of the text form +	const char **linesForm = 0; +	int countQuotes = 0; +	int strings=1; +	for (int j=0; countQuotes < (2*strings); j++) { +		if (textForm[j] == '\"') { +			if (countQuotes == 0) { +				const char *line0 = textForm + j + 1; +				// Skip width +				line0 = NextField(line0); +				// Add 1 line for each pixel of height +				strings += atoi(line0); +				line0 = NextField(line0); +				// Add 1 line for each colour +				strings += atoi(line0); +				linesForm = new const char *[strings]; +			} +			if (linesForm && ((countQuotes & 1) == 0)) { +				linesForm[countQuotes / 2] = textForm + j + 1; +			} +			countQuotes++; +		} +	} +	return linesForm; +} + +// In future, may want to minimize search time by sorting and using a binary search. + +XPMSet::XPMSet() : set(0), len(0), maximum(0), height(-1), width(-1) { +} + +XPMSet::~XPMSet() { +	Clear(); +} + +void XPMSet::Clear() { +	for (int i=0;i<maximum;i++) { +		delete set[i]; +	} +	delete []set; +	set = 0; +	len = 0; +	maximum = 0; +	height = -1; +	width = -1; +} + +void XPMSet::Add(int id, const char *textForm) { +	// Invalidate cached dimensions +	height = -1; +	width = -1; + +	// Replace if this id already present +	for (int i=0;i<maximum;i++) { +		if (set[i]->GetId() == id) { +			set[i]->Init(textForm); +			return; +		} +	} + +	// No present, so add to end +	XPM *pxpm = new XPM(textForm); +	if (pxpm) { +		pxpm->SetId(id); +		pxpm->CopyDesiredColours(); +		if (len == maximum) { +			int lenNew = len + 100; +			XPM **setNew = new XPM *[lenNew]; +			for (int i=0; i<maximum; i++) { +				setNew[i] = set[i]; +			} +			delete []set; +			set = setNew; +		} +		set[maximum] = pxpm; +		maximum++; +	} +} + +XPM *XPMSet::Get(int id) { +	for (int i=0;i<maximum;i++) { +		if (set[i]->GetId() == id) { +			return set[i]; +		} +	} +	return 0; +} + +int XPMSet::GetHeight() { +	if (height < 0) { +		for (int i=0; i<maximum; i++) { +			if (height < set[i]->GetHeight()) { +				height = set[i]->GetHeight(); +			} +		} +	} +	return (height > 0) ? height : 0; +} + +int XPMSet::GetWidth() { +	if (width < 0) { +		for (int i=0; i<maximum; i++) { +			if (width < set[i]->GetWidth()) { +				width = set[i]->GetWidth(); +			} +		} +	} +	return (width > 0) ? width : 0; +} diff --git a/src/XPM.h b/src/XPM.h new file mode 100644 index 000000000..948e557a9 --- /dev/null +++ b/src/XPM.h @@ -0,0 +1,67 @@ +// Scintilla source code edit control +/** @file XPM.h + ** Define a class that holds data in the X Pixmap (XPM) format, + **/ +// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef XPM_H +#define XPM_H + +/** + * Hold a pixmap in XPM format. + */ +class XPM { +	int id;		// Assigned by container +	int height; +	int width; +	int nColours; +	char *data; +	char codeTransparent; +	char *codes; +	ColourPair *colours; +	ColourAllocated ColourFromCode(int ch); +	void FillRun(Surface *surface, int code, int startX, int y, int x); +	char **lines; +	ColourPair *colourCodeTable[256]; +public: +	XPM(const char *textForm); +	XPM(const char * const *linesForm); +	~XPM(); +	void Init(const char *textForm); +	void Init(const char * const *linesForm); +	void Clear(); +	// Similar to same named method in ViewStyle: +	void RefreshColourPalette(Palette &pal, bool want); +	// No palette used, so just copy the desired colours to the allocated colours: +	void CopyDesiredColours(); +	// Decompose image into runs and use FillRectangle for each run: +	void Draw(Surface *surface, PRectangle &rc); +	char **InLinesForm() { return lines; } +	void SetId(int id_) { id = id_; } +	int GetId() { return id; } +	int GetHeight() { return height; } +	int GetWidth() { return width; } +	static const char **LinesFormFromTextForm(const char *textForm); +}; + +/** + * A collection of pixmaps indexed by integer id. + */ +class XPMSet { +	XPM **set; +	int len; +	int maximum; +	int height; +	int width; +public: +	XPMSet(); +	~XPMSet(); +	void Clear(); +	void Add(int id, const char *textForm); +	XPM *Get(int id); +	int GetHeight(); +	int GetWidth(); +}; + +#endif | 
