aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornyamatongwe <unknown>2003-01-10 11:06:02 +0000
committernyamatongwe <unknown>2003-01-10 11:06:02 +0000
commit265b37457926befea52ffc34a35b9aea510f4887 (patch)
treea8c176637bf02315069c6d91835efd610ece5664
parent63ed30c73860930738658fa7445cb2bb215f5c43 (diff)
downloadscintilla-mirror-265b37457926befea52ffc34a35b9aea510f4887.tar.gz
Initial version.
-rw-r--r--src/XPM.cxx297
-rw-r--r--src/XPM.h67
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