summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlordjaxom <lordjaxom>2004-12-12 19:53:30 +0000
committerlordjaxom <lordjaxom>2004-12-12 19:53:30 +0000
commit3b0999969632e2820b846ca8adcef6b346ff7441 (patch)
tree1582ed7db886839ea06c226e228eade0516f60c2
parente4c359b5c303cecfc49fb82799805da9fee8dadb (diff)
downloadvdr-plugin-text2skin-3b0999969632e2820b846ca8adcef6b346ff7441.tar.gz
vdr-plugin-text2skin-3b0999969632e2820b846ca8adcef6b346ff7441.tar.bz2
1.0-pre3v1.0-pre3
-rw-r--r--Makefile6
-rw-r--r--bitmap.c48
-rw-r--r--bitmap.h6
-rw-r--r--cache.c4
-rw-r--r--cache.h5
-rw-r--r--display.c41
-rw-r--r--display.h13
-rw-r--r--loader.c11
-rw-r--r--quantize.c415
-rw-r--r--quantize.h71
-rw-r--r--render.c28
-rw-r--r--render.h25
-rw-r--r--text2skin.c4
-rw-r--r--xml/function.c23
-rw-r--r--xml/function.h4
-rw-r--r--xml/parser.c61
-rw-r--r--xml/string.c1
-rw-r--r--xml/type.c5
-rw-r--r--xml/type.h2
-rw-r--r--xml/xml.c32
20 files changed, 683 insertions, 122 deletions
diff --git a/Makefile b/Makefile
index aba3e9c..9dd7165 100644
--- a/Makefile
+++ b/Makefile
@@ -55,7 +55,7 @@ PACKAGE = vdr-$(ARCHIVE)
OBJS = $(PLUGIN).o loader.o display.o render.o common.o bitmap.o \
file.o i18n.o theme.o cache.o setup.o status.o scroller.o screen.o \
- menu.o font.o \
+ menu.o font.o quantize.o \
\
xml/skin.o xml/parser.o xml/string.o xml/object.o xml/function.o \
xml/type.o xml/display.o xml/xml.o
@@ -86,13 +86,13 @@ ifdef HAVE_FREETYPE
endif
ifdef DEBUG
- CXXFLAGS += -O2 -g
+ CXXFLAGS += -g -fno-inline
DEFINES += -DDEBUG
else
CXXFLAGS += -O2
endif
-INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include -I.
+INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/linux/include -I$(DVBDIR)/include -I.
DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
diff --git a/bitmap.c b/bitmap.c
index fa76c29..0cbc417 100644
--- a/bitmap.c
+++ b/bitmap.c
@@ -3,6 +3,7 @@
*/
#include "bitmap.h"
+#include "quantize.h"
#include "setup.h"
#include <vdr/tools.h>
#define X_DISPLAY_MISSING
@@ -16,7 +17,7 @@ using namespace Magick;
cText2SkinCache cText2SkinBitmap::mCache(Text2SkinSetup.MaxCacheFill);
-cText2SkinBitmap *cText2SkinBitmap::Load(const std::string &Filename, int Alpha) {
+cText2SkinBitmap *cText2SkinBitmap::Load(const std::string &Filename, int Alpha, int height, int width, int colors) {
if (mCache.Contains(Filename))
return mCache[Filename];
else {
@@ -28,10 +29,10 @@ cText2SkinBitmap *cText2SkinBitmap::Load(const std::string &Filename, int Alpha)
result = bmp->LoadXpm(Filename.c_str());
else {
#ifdef HAVE_IMLIB2
- result = bmp->LoadImlib(Filename.c_str());
+ result = bmp->LoadImlib(Filename.c_str(),height,width,colors);
#else
# ifdef HAVE_IMAGEMAGICK
- result = bmp->LoadMagick(Filename.c_str());
+ result = bmp->LoadMagick(Filename.c_str(),height,width,colors);
# else
esyslog("ERROR: text2skin: unknown file format for %s", Filename);
# endif
@@ -109,34 +110,52 @@ bool cText2SkinBitmap::LoadXpm(const char *Filename) {
}
#ifdef HAVE_IMLIB2
-bool cText2SkinBitmap::LoadImlib(const char *Filename) {
+bool cText2SkinBitmap::LoadImlib(const char *Filename, int height, int width, int colors) {
Imlib_Image image;
+ unsigned char * outputImage = NULL;
+ unsigned int * outputPalette = NULL;
+ cQuantizeWu* quantizer = new cQuantizeWu();
cBitmap *bmp = NULL;
image = imlib_load_image(Filename);
if (!image)
return false;
Imlib_Context ctx = imlib_context_new();
imlib_context_push(ctx);
+ if (height != 0 || width != 0){
+ imlib_context_set_image(image);
+ image = imlib_create_cropped_scaled_image(0,0,imlib_image_get_width(), imlib_image_get_height() ,width , height);
+ }
imlib_context_set_image(image);
bmp = new cBitmap(imlib_image_get_width(), imlib_image_get_height(), 8);
uint8_t *data = (uint8_t*)imlib_image_get_data_for_reading_only();
- int pal = 0, pos = 0;
+ if ( colors != 0 ){
+ quantizer->Quantize(data, imlib_image_get_width()* imlib_image_get_height(), colors);
+ outputImage = quantizer->OutputImage();
+ outputPalette = quantizer->OutputPalette();
+ }
+ int pos = 0;
for (int y = 0; y < bmp->Height(); ++y) {
for (int x = 0; x < bmp->Width(); ++x) {
- tColor col = (data[pos + 3] << 24) | (data[pos + 2] << 16) | (data[pos + 1] << 8) | data[pos + 0];
- bmp->DrawPixel(x, y, col);
- pos += 4;
+ if ( colors != 0 ){
+ bmp->DrawPixel(x, y , outputPalette[outputImage[y * bmp->Width() + x]] | 0xFF000000 );
+ }else{
+ tColor col = (data[pos + 3] << 24) | (data[pos + 2] << 16) | (data[pos + 1] << 8) | data[pos + 0];
+ bmp->DrawPixel(x, y, col);
+ pos += 4;
+ }
}
}
+
imlib_free_image();
imlib_context_free(ctx);
mBitmaps.push_back(bmp);
+ delete(quantizer);
return true;
}
#endif
#ifdef HAVE_IMAGEMAGICK
-bool cText2SkinBitmap::LoadMagick(const char *Filename) {
+bool cText2SkinBitmap::LoadMagick(const char *Filename, int height, int width, int colors) {
std::vector<Image> images;
cBitmap *bmp = NULL;
try {
@@ -149,6 +168,15 @@ bool cText2SkinBitmap::LoadMagick(const char *Filename) {
}
mDelay = images[0].animationDelay() * 10;
for (it = images.begin(); it != images.end(); ++it) {
+ if (colors != 0){
+ (*it).opacity(OpaqueOpacity);
+ (*it).backgroundColor( Color ( 0,0,0,0) );
+ (*it).quantizeColorSpace( RGBColorspace );
+ (*it).quantizeColors( colors );
+ (*it).quantize();
+ }
+ if (height != 0 || width != 0)
+ (*it).sample(Geometry(width,height));
w = (*it).columns();
h = (*it).rows();
if ((*it).depth() > 8) {
@@ -156,7 +184,7 @@ bool cText2SkinBitmap::LoadMagick(const char *Filename) {
return false;
}
bmp = new cBitmap(w, h, (*it).depth());
- Dprintf("this image has %d colors\n", (*it).totalColors());
+ //Dprintf("this image has %d colors\n", (*it).totalColors());
const PixelPacket *pix = (*it).getConstPixels(0, 0, w, h);
for (int iy = 0; iy < h; ++iy) {
diff --git a/bitmap.h b/bitmap.h
index af0fd42..632408e 100644
--- a/bitmap.h
+++ b/bitmap.h
@@ -22,7 +22,7 @@ private:
cText2SkinBitmap(void);
public:
- static cText2SkinBitmap *Load(const std::string &Filename, int Alpha = 0);
+ static cText2SkinBitmap *Load(const std::string &Filename, int Alpha = 0, int height = 0, int width = 0, int colors = 0);
static void ResetCache(void) { mCache.Reset(); }
static void FlushCache(void) { mCache.Flush(); }
@@ -35,10 +35,10 @@ public:
bool LoadXpm(const char *Filename);
#ifdef HAVE_IMLIB2
- bool LoadImlib(const char *Filename);
+ bool LoadImlib(const char *Filename,int height = 0, int width = 0, int colors = 0);
#endif
#ifdef HAVE_IMAGEMAGICK
- bool LoadMagick(const char *Filename);
+ bool LoadMagick(const char *Filename,int height = 0, int width = 0, int colors = 0);
#endif
};
diff --git a/cache.c b/cache.c
index b5026b7..6c3f99a 100644
--- a/cache.c
+++ b/cache.c
@@ -1,5 +1,5 @@
/*
- * $Id: cache.c,v 1.2 2004/12/08 18:47:37 lordjaxom Exp $
+ * $Id: cache.c,v 1.2 2004/06/18 16:08:11 lordjaxom Exp $
*/
#include "cache.h"
@@ -13,7 +13,7 @@ cText2SkinCache::~cText2SkinCache() {
Flush();
}
-void cText2SkinCache::Delete(const key_type &/*Key*/, data_type &Data) {
+void cText2SkinCache::Delete(const key_type &Key, data_type &Data) {
delete Data;
}
diff --git a/cache.h b/cache.h
index 3734293..61b77e2 100644
--- a/cache.h
+++ b/cache.h
@@ -1,14 +1,15 @@
/*
- * $Id: cache.h,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
+ * $Id: cache.h,v 1.5 2004/06/18 16:08:11 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_CACHE_HPP
#define VDR_TEXT2SKIN_CACHE_HPP
#include "common.h"
+#include <vdr/tools.h>
#include <map>
#include <vector>
-#include <vdr/tools.h>
+#include <string>
class cText2SkinBitmap;
diff --git a/display.c b/display.c
index 05d1768..b3d0d5f 100644
--- a/display.c
+++ b/display.c
@@ -1,5 +1,5 @@
/*
- * $Id: display.c,v 1.5 2004/12/08 18:47:37 lordjaxom Exp $
+ * $Id: display.c,v 1.6 2004/12/10 21:46:46 lordjaxom Exp $
*/
#include "render.h"
@@ -23,6 +23,7 @@ cText2SkinDisplayChannel::cText2SkinDisplayChannel(cText2SkinLoader *Loader, boo
}
cText2SkinDisplayChannel::~cText2SkinDisplayChannel() {
+ Dprintf("~cTe...\n");
}
void cText2SkinDisplayChannel::SetChannel(const cChannel *Channel, int Number) {
@@ -50,6 +51,10 @@ void cText2SkinDisplayChannel::SetMessage(eMessageType Type, const char *Text) {
SetDirty();
}
}
+
+void cText2SkinDisplayChannel::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue) {
+ Dprintf("SetButtons(%s, %s, %s, %s)\n", Red, Green, Yellow, Blue);
+}
void cText2SkinDisplayChannel::Flush(void) {
cText2SkinRender::Flush();
@@ -100,7 +105,7 @@ cxType cText2SkinDisplayChannel::GetTokenData(const txToken &Token) {
case tPresentDuration:
return mPresent != NULL
? (cxType)TimeType(mPresent->Duration(), Token.Attrib)
- : (cxType)false;
+ : (cxType)false;
case tPresentTitle:
return mPresent != NULL
@@ -535,6 +540,7 @@ cText2SkinDisplayMenu::~cText2SkinDisplayMenu() {
void cText2SkinDisplayMenu::Clear(void) {
mItems.clear();
+ mCurrentItem = (uint)-1;
mEvent = NULL;
mRecording = NULL;
mText = "";
@@ -576,32 +582,35 @@ void cText2SkinDisplayMenu::SetMessage(eMessageType Type, const char *Text) {
void cText2SkinDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable) {
if (Text == NULL)
return;
+ Dprintf("SetItem(%s)\n", Text);
- tListItem item;
- item.text = Text;
- item.sel = Selectable;
+ tListItem *item = new tListItem(Text, Selectable);
+ //item.text = Text;
+ //item.sel = Selectable;
for (int i = 0; i < MaxTabs; ++i) {
const char *tab = GetTabbedText(Text, i);
if (tab)
- item.tabs[i] = tab;
+ item->tabs[i] = tab;
if (!Tab(i + 1))
break;
}
if (mItems.size() <= (uint)Index) {
- mItems.push_back(item);
+ mItems.push_back(*item);
SetDirty();
}
- else if (mItems[Index] != item) {
- mItems[Index] = item;
+ else if (mItems[Index] != *item) {
+ mItems[Index] = *item;
SetDirty();
}
+ delete item;
- if (Current && mCurrentItem != Index) {
+ if (Current && mCurrentItem != (uint)Index) {
mCurrentItem = Index;
SetDirty();
}
+ Dprintf("end SetItem()\n");
}
void cText2SkinDisplayMenu::SetEvent(const cEvent *Event) {
@@ -664,26 +673,28 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token) {
case tMenuItem:
return mItems.size() > (uint)Token.Index && mItems[Token.Index].sel
- && mCurrentItem != Token.Index
+ && mCurrentItem != (uint)Token.Index
? (cxType)mItems[Token.Index].tabs[Token.Tab]
: (cxType)false;
case tIsMenuItem:
return mItems.size() > (uint)Token.Index && mItems[Token.Index].sel
- && mCurrentItem != Token.Index;
+ && mCurrentItem != (uint)Token.Index;
case tMenuCurrent:
if (Token.Index < 0)
- return mItems[mCurrentItem].text;
+ return mItems.size() > mCurrentItem
+ ? (cxType)mItems[mCurrentItem].text
+ : (cxType)false;
return mItems.size() > (uint)Token.Index && mItems[Token.Index].sel
- && mCurrentItem == Token.Index
+ && mCurrentItem == (uint)Token.Index
? (cxType)mItems[Token.Index].tabs[Token.Tab]
: (cxType)false;
case tIsMenuCurrent:
return mItems.size() > (uint)Token.Index && mItems[Token.Index].sel
- && mCurrentItem == Token.Index;
+ && mCurrentItem == (uint)Token.Index;
case tMenuGroup:
return mItems.size() > (uint)Token.Index && !mItems[Token.Index].sel
diff --git a/display.h b/display.h
index f205c8a..f12bb83 100644
--- a/display.h
+++ b/display.h
@@ -1,5 +1,5 @@
/*
- * $Id: display.h,v 1.4 2004/12/08 18:47:37 lordjaxom Exp $
+ * $Id: display.h,v 1.5 2004/12/10 21:46:46 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_SKIN_H
@@ -34,14 +34,15 @@ public:
virtual void SetChannel(const cChannel *Channel, int Number);
virtual void SetEvents(const cEvent *Present, const cEvent *Following);
virtual void SetMessage(eMessageType Type, const char *Text);
+ virtual void SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue);
virtual void Flush(void);
};
class cText2SkinDisplayVolume: public cSkinDisplayVolume, public cText2SkinRender {
private:
- int mCurrent;
- int mTotal;
- int mMute;
+ int mCurrent;
+ int mTotal;
+ bool mMute;
protected:
virtual cxType GetTokenData(const txToken &Token);
@@ -128,11 +129,13 @@ private:
std::string tabs[MaxTabs];
bool sel;
+ tListItem(const std::string &Text, bool Sel): text(Text), sel(Sel) {}
+
bool operator!=(const tListItem &b) { return b.text != text || b.sel != sel; }
};
std::vector<tListItem> mItems;
- int mCurrentItem;
+ uint mCurrentItem;
protected:
virtual cxType GetTokenData(const txToken &Token);
diff --git a/loader.c b/loader.c
index c08c8f1..d4bc27f 100644
--- a/loader.c
+++ b/loader.c
@@ -16,15 +16,16 @@
void cText2SkinLoader::Start(void) {
DIR *d = opendir(SkinPath().c_str());
if (d) {
- struct dirent *ent;
- while ((ent = readdir(d)) != NULL) {
+ struct dirent ent;
+ struct dirent *result;
+ while ((readdir_r(d, &ent, &result)) == 0 && result != NULL) {
char *path;
struct stat buf;
- if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
+ if (strcmp(result->d_name, ".") == 0 || strcmp(result->d_name, "..") == 0)
continue;
- asprintf(&path, "%s/%s", SkinPath().c_str(), ent->d_name);
+ asprintf(&path, "%s/%s", SkinPath().c_str(), result->d_name);
if (stat(path, &buf) == 0 && S_ISDIR(buf.st_mode))
- Load(ent->d_name);
+ Load(result->d_name);
free(path);
}
closedir(d);
diff --git a/quantize.c b/quantize.c
new file mode 100644
index 0000000..84546f5
--- /dev/null
+++ b/quantize.c
@@ -0,0 +1,415 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "quantize.h"
+
+cQuantizeWu::cQuantizeWu()
+{
+}
+
+cQuantizeWu::~cQuantizeWu()
+{
+}
+
+#define WEIG //>>2
+int cQuantizeWu::Quantize(unsigned char * input, int size, int colors)
+{
+ struct box cube[MAXCOLOR];
+ int next;
+ int i;
+ int j;
+ int k;
+ int l;
+ float vv[MAXCOLOR];
+ float temp;
+ unsigned char * tag;
+ long weight;
+
+ imageInput = input;
+ imageSize = size;
+ palSize = colors;
+
+ for (j = 0; j < BOX; j++)
+ for (k = 0; k < BOX; k++)
+ for (l = 0; l < BOX; l++)
+ {
+ wt[j][k][l] = 0;
+ mr[j][k][l] = 0;
+ mg[j][k][l] = 0;
+ mb[j][k][l] = 0;
+ m2[j][k][l] = 0.0;
+ }
+
+ Qadd = new unsigned short[imageSize * sizeof(unsigned short)];
+ Hist3d((long *)&wt, (long *)&mr, (long *)&mg, (long *)&mb, (float *)&m2);
+ Momt3d((long *)&wt, (long *)&mr, (long *)&mg, (long *)&mb, (float *)&m2);
+
+ cube[0].r0 = cube[0].g0 = cube[0].b0 = 0;
+ cube[0].r1 = cube[0].g1 = cube[0].b1 = 32;
+
+ next = 0;
+ for (i = 1; i < palSize; i++)
+ {
+ if (Cut(&cube[next], &cube[i]))
+ {
+ vv[next] = (cube[next].vol > 1) ? Var(&cube[next]) : 0.0;
+ vv[i] = (cube[i].vol > 1) ? Var(&cube[i]) : 0.0;
+ }
+ else
+ {
+ vv[next] = 0.0;
+ i--;
+ }
+ next = 0;
+ temp = vv[0];
+ for (k = 1; k <= i; k++)
+ if (vv[k] > temp)
+ {
+ temp = vv[k];
+ next = k;
+ }
+ if (temp <= 0.0)
+ {
+ palSize = i + 1;
+ break;
+ }
+ }
+
+ tag = new unsigned char[BOX * BOX * BOX];
+
+ unsigned char * palette = (unsigned char *) paletteOutput;
+ for (k = 0; k < palSize; ++k)
+ {
+ Mark(&cube[k], k, tag);
+ weight = Vol(&cube[k], wt);
+ if (weight)
+ {
+#ifdef NOINVERT
+ palette[k * 4 + 2] = (Vol(&cube[k], mb) / weight) WEIG;
+ palette[k * 4 + 0] = (Vol(&cube[k], mr) / weight) WEIG;
+#else
+ palette[k * 4 + 0] = (Vol(&cube[k], mb) / weight) WEIG;
+ palette[k * 4 + 2] = (Vol(&cube[k], mr) / weight) WEIG;
+#endif
+ palette[k * 4 + 1] = (Vol(&cube[k], mg) / weight) WEIG;
+ }
+ else
+ {
+ palette[k * 4 + 0] = 0;
+ palette[k * 4 + 1] = 0;
+ palette[k * 4 + 2] = 0;
+ }
+ }
+
+ for (i = 0; i < imageSize; i++)
+ {
+ imageOutput[i] = tag[Qadd[i]];
+ }
+
+ delete[] tag;
+ delete[] Qadd;
+
+ return 0;
+}
+
+// build 3-D color histogram of counts, r/g/b, c^2
+void cQuantizeWu::Hist3d(long *vwt, long *vmr, long *vmg, long *vmb, float *m_2)
+{
+ int ind;
+ int r;
+ int g;
+ int b;
+ int inr;
+ int ing;
+ int inb;
+ int table[256];
+ int i;
+
+ for (i = 0; i < 256; i++)
+ table[i] = i * i;
+
+ for (i = 0; i < imageSize; i++)
+ {
+ b = imageInput[i*4];
+ g = imageInput[i*4+1];
+ r = imageInput[i*4+2];
+
+ inr = (r >> 3) + 1;
+ ing = (g >> 3) + 1;
+ inb = (b >> 3) + 1;
+ Qadd[i] = ind = (inr << 10) + (inr << 6) + inr + (ing << 5) + ing + inb;
+
+ vwt[ind]++;
+ vmr[ind] += r;
+ vmg[ind] += g;
+ vmb[ind] += b;
+ m_2[ind] += (float) (table[r] + table[g] + table[b]);
+ }
+}
+
+// We now convert histogram into moments so that we can rapidly calculate
+// the sums of the above quantities over any desired box.
+void cQuantizeWu::Momt3d(long *vwt, long *vmr, long *vmg, long *vmb, float *m_2)
+{
+ unsigned short ind1;
+ unsigned short ind2;
+ unsigned char i;
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+ long line;
+ long line_r;
+ long line_g;
+ long line_b;
+ long area[BOX];
+ long area_r[BOX];
+ long area_g[BOX];
+ long area_b[BOX];
+ float line2;
+ float area2[BOX];
+
+ for (r = 1; r <= 32; ++r)
+ {
+ for (i = 0; i <= 32; ++i)
+ area2[i] = area[i] = area_r[i] = area_g[i] = area_b[i] = 0;
+ for (g = 1; g <= 32; ++g)
+ {
+ line2 = line = line_r = line_g = line_b = 0;
+ for (b = 1; b <= 32; ++b)
+ {
+ ind1 = (r << 10) + (r << 6) + r + (g << 5) + g + b;
+ line += vwt[ind1];
+ line_r += vmr[ind1];
+ line_g += vmg[ind1];
+ line_b += vmb[ind1];
+ line2 += m_2[ind1];
+ area[b] += line;
+ area_r[b] += line_r;
+ area_g[b] += line_g;
+ area_b[b] += line_b;
+ area2[b] += line2;
+ ind2 = ind1 - 1089; /* [r-1][g][b] */
+ vwt[ind1] = vwt[ind2] + area[b];
+ vmr[ind1] = vmr[ind2] + area_r[b];
+ vmg[ind1] = vmg[ind2] + area_g[b];
+ vmb[ind1] = vmb[ind2] + area_b[b];
+ m_2[ind1] = m_2[ind2] + area2[b];
+ }
+ }
+ }
+}
+
+int cQuantizeWu::Cut(struct box * set1, struct box * set2)
+{
+ unsigned char dir;
+ int cutr;
+ int cutg;
+ int cutb;
+ float maxr;
+ float maxg;
+ float maxb;
+ long whole_r;
+ long whole_g;
+ long whole_b;
+ long whole_w;
+
+ whole_r = Vol(set1, mr);
+ whole_g = Vol(set1, mg);
+ whole_b = Vol(set1, mb);
+ whole_w = Vol(set1, wt);
+
+ maxr = Maximize(set1, RED, set1->r0 + 1, set1->r1, &cutr,
+ whole_r, whole_g, whole_b, whole_w);
+ maxg = Maximize(set1, GREEN, set1->g0 + 1, set1->g1, &cutg,
+ whole_r, whole_g, whole_b, whole_w);
+ maxb = Maximize(set1, BLUE, set1->b0 + 1, set1->b1, &cutb,
+ whole_r, whole_g, whole_b, whole_w);
+
+ if ((maxr >= maxg) && (maxr >= maxb))
+ {
+ dir = RED;
+ if (cutr < 0)
+ return 0; /* can't split the box */
+ }
+ else if ((maxg >= maxr) && (maxg >= maxb))
+ dir = GREEN;
+ else
+ dir = BLUE;
+
+ set2->r1 = set1->r1;
+ set2->g1 = set1->g1;
+ set2->b1 = set1->b1;
+
+ switch (dir)
+ {
+ case RED:
+ set2->r0 = set1->r1 = cutr;
+ set2->g0 = set1->g0;
+ set2->b0 = set1->b0;
+ break;
+ case GREEN:
+ set2->g0 = set1->g1 = cutg;
+ set2->r0 = set1->r0;
+ set2->b0 = set1->b0;
+ break;
+ case BLUE:
+ set2->b0 = set1->b1 = cutb;
+ set2->r0 = set1->r0;
+ set2->g0 = set1->g0;
+ break;
+ }
+ set1->vol = (set1->r1 - set1->r0) * (set1->g1 - set1->g0) * (set1->b1 - set1->b0);
+ set2->vol = (set2->r1 - set2->r0) * (set2->g1 - set2->g0) * (set2->b1 - set2->b0);
+ return 1;
+}
+
+long cQuantizeWu::Vol(struct box * cube, long mmt[BOX][BOX][BOX])
+{
+ return (mmt[cube->r1][cube->g1][cube->b1]
+ - mmt[cube->r1][cube->g1][cube->b0]
+ - mmt[cube->r1][cube->g0][cube->b1]
+ + mmt[cube->r1][cube->g0][cube->b0]
+ - mmt[cube->r0][cube->g1][cube->b1]
+ + mmt[cube->r0][cube->g1][cube->b0]
+ + mmt[cube->r0][cube->g0][cube->b1]
+ - mmt[cube->r0][cube->g0][cube->b0]);
+}
+
+float cQuantizeWu::Maximize(struct box * cube, unsigned char dir, int first, int last, int * cut, long whole_r, long whole_g, long whole_b, long whole_w)
+{
+ long half_r;
+ long half_g;
+ long half_b;
+ long half_w;
+ long base_r;
+ long base_g;
+ long base_b;
+ long base_w;
+ int i;
+ float temp;
+ float max;
+
+ base_r = Bottom(cube, dir, mr);
+ base_g = Bottom(cube, dir, mg);
+ base_b = Bottom(cube, dir, mb);
+ base_w = Bottom(cube, dir, wt);
+ max = 0.0;
+ *cut = -1;
+ for (i = first; i < last; i++)
+ {
+ half_r = base_r + Top(cube, dir, i, mr);
+ half_g = base_g + Top(cube, dir, i, mg);
+ half_b = base_b + Top(cube, dir, i, mb);
+ half_w = base_w + Top(cube, dir, i, wt);
+ // now half_x is sum over lower half of box, if split at i
+ if (half_w == 0)
+ {
+ // subbox could be empty of pixels!
+ continue; // never split into an empty box
+ }
+ else
+ temp = ((float) half_r * half_r + (float) half_g * half_g + (float) half_b * half_b) / half_w;
+
+ half_r = whole_r - half_r;
+ half_g = whole_g - half_g;
+ half_b = whole_b - half_b;
+ half_w = whole_w - half_w;
+ if (half_w == 0)
+ {
+ // subbox could be empty of pixels!
+ continue; // never split into an empty box
+ }
+ else
+ temp += ((float) half_r * half_r + (float) half_g * half_g + (float) half_b * half_b) / half_w;
+
+ if (temp > max)
+ {
+ max = temp;
+ *cut = i;
+ }
+ }
+ return (max);
+}
+
+float cQuantizeWu::Var(struct box * cube)
+{
+ float dr;
+ float dg;
+ float db;
+ float xx;
+
+ dr = Vol(cube, mr);
+ dg = Vol(cube, mg);
+ db = Vol(cube, mb);
+ xx = m2[cube->r1][cube->g1][cube->b1]
+ - m2[cube->r1][cube->g1][cube->b0]
+ - m2[cube->r1][cube->g0][cube->b1]
+ + m2[cube->r1][cube->g0][cube->b0]
+ - m2[cube->r0][cube->g1][cube->b1]
+ + m2[cube->r0][cube->g1][cube->b0]
+ + m2[cube->r0][cube->g0][cube->b1]
+ - m2[cube->r0][cube->g0][cube->b0];
+
+ return (xx - (dr * dr + dg * dg + db * db) / (float) Vol(cube, wt));
+}
+
+long cQuantizeWu::Bottom(struct box * cube, unsigned char dir, long mmt[BOX][BOX][BOX])
+{
+ switch (dir)
+ {
+ case RED:
+ return (-mmt[cube->r0][cube->g1][cube->b1]
+ + mmt[cube->r0][cube->g1][cube->b0]
+ + mmt[cube->r0][cube->g0][cube->b1]
+ - mmt[cube->r0][cube->g0][cube->b0]);
+ case GREEN:
+ return (-mmt[cube->r1][cube->g0][cube->b1]
+ + mmt[cube->r1][cube->g0][cube->b0]
+ + mmt[cube->r0][cube->g0][cube->b1]
+ - mmt[cube->r0][cube->g0][cube->b0]);
+ case BLUE:
+ return (-mmt[cube->r1][cube->g1][cube->b0]
+ + mmt[cube->r1][cube->g0][cube->b0]
+ + mmt[cube->r0][cube->g1][cube->b0]
+ - mmt[cube->r0][cube->g0][cube->b0]);
+ }
+ printf("error in Bottom()");
+ return 0;
+}
+
+long cQuantizeWu::Top(struct box * cube, unsigned char dir, int pos, long mmt[BOX][BOX][BOX])
+{
+ switch (dir)
+ {
+ case RED:
+ return (mmt[pos][cube->g1][cube->b1]
+ - mmt[pos][cube->g1][cube->b0]
+ - mmt[pos][cube->g0][cube->b1]
+ + mmt[pos][cube->g0][cube->b0]);
+ case GREEN:
+ return (mmt[cube->r1][pos][cube->b1]
+ - mmt[cube->r1][pos][cube->b0]
+ - mmt[cube->r0][pos][cube->b1]
+ + mmt[cube->r0][pos][cube->b0]);
+ case BLUE:
+ return (mmt[cube->r1][cube->g1][pos]
+ - mmt[cube->r1][cube->g0][pos]
+ - mmt[cube->r0][cube->g1][pos]
+ + mmt[cube->r0][cube->g0][pos]);
+ }
+ printf("error in Top()");
+ return 0;
+}
+
+void cQuantizeWu::Mark(struct box * cube, int label, unsigned char * tag)
+{
+ int r;
+ int g;
+ int b;
+
+ for (r = cube->r0 + 1; r <= cube->r1; r++)
+ for (g = cube->g0 + 1; g <= cube->g1; g++)
+ for (b = cube->b0 + 1; b <= cube->b1; b++)
+ tag[(r << 10) + (r << 6) + r + (g << 5) + g + b] = label;
+
+}
diff --git a/quantize.h b/quantize.h
new file mode 100644
index 0000000..af6a623
--- /dev/null
+++ b/quantize.h
@@ -0,0 +1,71 @@
+#ifndef VDR_GRAPHTFT_QUANTIZE_H
+#define VDR_GRAPHTFT_QUANTIZE_H
+
+#define MAXCOLOR 256
+
+class cQuantize
+{
+protected:
+ unsigned int paletteOutput[MAXCOLOR];
+ unsigned char imageOutput[1024*1024];
+public:
+ cQuantize(){};
+ virtual ~cQuantize(){};
+ virtual int Quantize(unsigned char * input, int size, int colors) = 0;
+ unsigned int * OutputPalette() { return paletteOutput; }
+ unsigned char * OutputImage() { return imageOutput; }
+};
+
+#define RED 2
+#define GREEN 1
+#define BLUE 0
+
+//#define NOINVERT // RGB or BGR
+
+struct box
+{
+ int r0;
+ int r1;
+ int g0;
+ int g1;
+ int b0;
+ int b1;
+ int vol;
+};
+
+// Histogram is in elements 1..HISTSIZE along each axis,
+// element 0 is for base or marginal value.
+// NB: these must start out 0!
+#define BOX 33
+
+class cQuantizeWu : public cQuantize
+{
+private:
+ long wt[BOX][BOX][BOX];
+ long mr[BOX][BOX][BOX];
+ long mg[BOX][BOX][BOX];
+ long mb[BOX][BOX][BOX];
+ float m2[BOX][BOX][BOX];
+
+ unsigned short * Qadd;
+
+ unsigned char * imageInput;
+ int imageSize;
+ int palSize;
+
+ void Hist3d(long *vwt, long *vmr, long *vmg, long *vmb, float *m_2);
+ void Momt3d(long *vwt, long *vmr, long *vmg, long *vmb, float *m_2);
+ int Cut(struct box * set1, struct box * set2);
+ long Vol(struct box * cube, long mmt[BOX][BOX][BOX]);
+ float Maximize(struct box * cube, unsigned char dir, int first, int last, int * cut, long whole_r, long whole_g, long whole_b, long whole_w);
+ float Var(struct box * cube);
+ long Top(struct box * cube, unsigned char dir, int pos, long mmt[BOX][BOX][BOX]);
+ long Bottom(struct box * cube, unsigned char dir, long mmt[BOX][BOX][BOX]);
+ void Mark(struct box * cube, int label, unsigned char * tag);
+public:
+ cQuantizeWu();
+ virtual ~cQuantizeWu();
+ virtual int Quantize(unsigned char * input, int size, int colors);
+};
+
+#endif // VDR_GRAPHTFT_QUANTIZE_H
diff --git a/render.c b/render.c
index dfbc0ba..502a3ca 100644
--- a/render.c
+++ b/render.c
@@ -1,5 +1,5 @@
/*
- * $Id: render.c,v 1.6 2004/12/08 18:47:37 lordjaxom Exp $
+ * $Id: render.c,v 1.7 2004/12/10 21:46:46 lordjaxom Exp $
*/
#include "render.h"
@@ -28,7 +28,9 @@ cText2SkinRender::cText2SkinRender(cText2SkinLoader *Loader, cxDisplay::eType Di
mDirty(true),
mActive(false),
mDoUpdate(),
- mMutex(),
+ mDoUpdateMutex(),
+ //mDoneUpdate(),
+ //mDoneUpdateMutex(),
mStarted(),
mUpdateIn(0),
mBaseSize()
@@ -87,10 +89,10 @@ cText2SkinRender::cText2SkinRender(cText2SkinLoader *Loader, cxDisplay::eType Di
}
if (!OffScreen) {
- Lock();
+ mDoUpdateMutex.Lock();
Start();
- mStarted.Wait(mMutex);
- Unlock();
+ mStarted.Wait(mDoUpdateMutex);
+ mDoUpdateMutex.Unlock();
}
}
@@ -108,18 +110,22 @@ cText2SkinRender::~cText2SkinRender() {
void cText2SkinRender::Action(void) {
mActive = true;
- Lock();
+ mDoUpdateMutex.Lock();
mStarted.Broadcast();
while (mActive) {
- if (mUpdateIn) mDoUpdate.TimedWait(mMutex, mUpdateIn);
- else mDoUpdate.Wait(mMutex);
+ if (mUpdateIn) mDoUpdate.TimedWait(mDoUpdateMutex, mUpdateIn);
+ else mDoUpdate.Wait(mDoUpdateMutex);
- if (!mActive) break; // fall out if thread to be stopped
+ if (!mActive) break; // fall out if thread to be stopped
mUpdateIn = 0; // has to be re-set within Update();
Update();
+
+ //mDoneUpdateMutex.Lock();
+ //mDoneUpdate.Broadcast();
+ //mDoneUpdateMutex.Unlock();
}
- Unlock();
+ mDoUpdateMutex.Unlock();
}
void cText2SkinRender::Update(void) {
@@ -243,7 +249,7 @@ void cText2SkinRender::DrawImage(const txPoint &Pos, const tColor *Bg, const tCo
const std::string &Path)
{
cText2SkinBitmap *bmp;
- //Dprintf("trying to draw image %s to %dx%d\n", ImagePath(Path).c_str(), Pos.x, Pos.y);
+ Dprintf("trying to draw image %s to %dx%d - alpha %d\n", ImagePath(Path).c_str(), Pos.x, Pos.y, Alpha);
if ((bmp = cText2SkinBitmap::Load(ImagePath(Path), Alpha)) != NULL) {
//Dprintf("success loading image\n");
if (Bg) bmp->SetColor(0, *Bg);
diff --git a/render.h b/render.h
index d5bc15f..0ce7d40 100644
--- a/render.h
+++ b/render.h
@@ -1,5 +1,5 @@
/*
- * $Id: render.h,v 1.5 2004/12/08 18:47:37 lordjaxom Exp $
+ * $Id: render.h,v 1.6 2004/12/10 21:46:46 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_RENDER_H
@@ -45,8 +45,11 @@ private:
// update thread
bool mActive;
+
cCondVar mDoUpdate;
- cMutex mMutex;
+ cMutex mDoUpdateMutex;
+ //cCondVar mDoneUpdate;
+ //cMutex mDoneUpdateMutex;
cCondVar mStarted;
int mUpdateIn;
@@ -55,8 +58,8 @@ private:
protected:
// Update thread
- void Lock(void) { mMutex.Lock(); }
- void Unlock(void) { mMutex.Unlock(); }
+ //void Lock(void) { mMutex.Lock(); }
+ //void Unlock(void) { mMutex.Unlock(); }
virtual void Action(void);
// Drawing operations
@@ -115,9 +118,19 @@ public:
inline void cText2SkinRender::Flush(bool Force) {
if (mDirty || Force) {
- Lock();
+ //mDoneUpdateMutex.Lock();
+
+ mDoUpdateMutex.Lock();
mDoUpdate.Broadcast();
- Unlock();
+ mDoUpdateMutex.Unlock();
+
+ //if (mActive) {
+ //Dprintf("flush wait\n");
+ //mDoneUpdate.Wait(mDoneUpdateMutex);
+ //Dprintf("flush wait done\n");
+ //}
+ //mDoneUpdateMutex.Unlock();
+
mDirty = false;
}
}
diff --git a/text2skin.c b/text2skin.c
index e9baa04..3c73107 100644
--- a/text2skin.c
+++ b/text2skin.c
@@ -3,7 +3,7 @@
*
* See the README file for copyright information and how to reach the author.
*
- * $Id: text2skin.c,v 1.2 2004/12/08 17:13:26 lordjaxom Exp $
+ * $Id: text2skin.c,v 1.3 2004/12/10 21:46:46 lordjaxom Exp $
*/
#include "text2skin.h"
@@ -12,7 +12,7 @@
#include "i18n.h"
#include "loader.h"
-const char *cText2SkinPlugin::VERSION = "1.0-pre2";
+const char *cText2SkinPlugin::VERSION = "1.0-pre3";
const char *cText2SkinPlugin::SKINVERSION = "1.0";
const char *cText2SkinPlugin::DESCRIPTION = "Loader for text-based skins";
diff --git a/xml/function.c b/xml/function.c
index f283c2c..3243257 100644
--- a/xml/function.c
+++ b/xml/function.c
@@ -1,15 +1,16 @@
/*
- * $Id: function.c,v 1.4 2004/12/08 18:47:37 lordjaxom Exp $
+ * $Id: function.c,v 1.5 2004/12/10 21:46:46 lordjaxom Exp $
*/
#include "xml/function.h"
#include "render.h"
#include "bitmap.h"
#include "common.h"
+#include <vdr/plugin.h>
#include <vdr/tools.h>
static const char *Internals[] = {
- "not", "and", "or", "equal", "file", "trans", NULL
+ "not", "and", "or", "equal", "file", "trans", "plugin", NULL
};
const std::string cxFunction::False = "";
@@ -129,6 +130,7 @@ bool cxFunction::Parse(const std::string &Text)
case fun_eq: ++params;
case fun_not:
case fun_trans:
+ case fun_plugin:
case fun_file: ++params;
default: break;
}
@@ -161,6 +163,19 @@ const std::string &cxFunction::FunFile(const std::string &Param) const
return cText2SkinBitmap::Load(path) ? Param : False;
}
+std::string cxFunction::FunPlugin(const std::string &Param) const
+{
+ Dprintf("FunPlugin: Get(%s)\n", Param.c_str());
+ cPlugin *p = cPluginManager::GetPlugin(Param.c_str());
+ if (p) {
+ const char *entry = p->MainMenuEntry();
+ Dprintf("Entry: |%s|\n", entry);
+ if (entry)
+ return entry;
+ }
+ return False;
+}
+
std::string cxFunction::Evaluate(void) const
{
switch (mType) {
@@ -185,6 +200,7 @@ std::string cxFunction::Evaluate(void) const
return False;
case fun_eq:
+ Dprintf("eq: |%s| <-> |%s|\n", mParams[0]->Evaluate().c_str(), mParams[1]->Evaluate().c_str());
return mParams[0]->Evaluate() == mParams[1]->Evaluate() ? True : False;
case fun_file:
@@ -192,6 +208,9 @@ std::string cxFunction::Evaluate(void) const
case fun_trans:
return tr(mParams[0]->Evaluate().c_str());
+
+ case fun_plugin:
+ return FunPlugin(mParams[0]->Evaluate());
default:
Dprintf("unknown function code\n");
diff --git a/xml/function.h b/xml/function.h
index a7d8838..49928af 100644
--- a/xml/function.h
+++ b/xml/function.h
@@ -27,7 +27,8 @@ public:
fun_or = INTERNAL + 3,
fun_eq = INTERNAL + 4,
fun_file = INTERNAL + 5,
- fun_trans = INTERNAL + 6
+ fun_trans = INTERNAL + 6,
+ fun_plugin = INTERNAL + 7
};
static const std::string False;
@@ -42,6 +43,7 @@ private:
protected:
const std::string &FunFile(const std::string &Param) const;
+ std::string FunPlugin(const std::string &Param) const;
public:
cxFunction(void);
diff --git a/xml/parser.c b/xml/parser.c
index 4b957be..8842d19 100644
--- a/xml/parser.c
+++ b/xml/parser.c
@@ -1,5 +1,5 @@
/*
- * $Id: parser.c,v 1.4 2004/12/08 17:13:26 lordjaxom Exp $
+ * $Id: parser.c,v 1.5 2004/12/10 21:46:46 lordjaxom Exp $
*/
#include "xml/parser.h"
@@ -11,49 +11,6 @@
#include <vector>
#include <string>
-#define STR_SKIN "skin"
-#define STR_DISPLAY "display"
-#define STR_ID "id"
-#define STR_WINDOW "window"
-#define STR_X1 "x1"
-#define STR_Y1 "y1"
-#define STR_X "x"
-#define STR_Y "y"
-#define STR_X2 "x2"
-#define STR_Y2 "y2"
-#define STR_BPP "bpp"
-#define STR_IMAGE "image"
-#define STR_PATH "path"
-#define STR_ALPHA "alpha"
-#define STR_TEXT "text"
-#define STR_CONDITION "condition"
-#define STR_NOT "not"
-#define STR_FILE "file"
-#define STR_COLOR "color"
-#define STR_ALIGN "align"
-#define STR_RECTANGLE "rectangle"
-#define STR_ELLIPSE "ellipse"
-#define STR_SLOPE "slope"
-#define STR_PROGRESS "progress"
-#define STR_BGCOLOR "bgcolor"
-#define STR_CURRENT "current"
-#define STR_TOTAL "total"
-#define STR_VERSION "version"
-#define STR_NAME "name"
-#define STR_SCREENBASE "screenBase"
-#define STR_FONT "font"
-#define STR_ARC "arc"
-
-#define MSG_BADTAG "ERROR: The tag %s was not expected in this context"
-#define MSG_BADENDTAG "ERROR: The tag %s was not expected in this context"
-#define MSG_BADATTR "ERROR: The attribute %s was not expected in tag %s"
-#define MSG_MISSATTR "ERROR: The tag %s lacks the attribute %s"
-#define MSG_BADVALUE "ERROR: %s is not allowed for attribute %s"
-#define MSG_PARSERR "ERROR: Parser error in %s:%d: %s"
-#define MSG_BADCDATA "ERROR: Bad character data"
-#define MSG_NOFILE "ERROR: Couldn't read %s: %m"
-#define MSG_MANYWINS "ERROR: Too many windows"
-
#define TAG_ERR_REMAIN(_context) do { \
esyslog("ERROR: Text2Skin: Unexpected tag %s within %s", \
name.c_str(), _context); \
@@ -132,7 +89,7 @@ static cxObject *parent = NULL;
static cxObject *object = NULL;
bool xStartElem(const std::string &name, std::map<std::string,std::string> &attrs) {
- Dprintf("start element: %s\n", name.c_str());
+ //Dprintf("start element: %s\n", name.c_str());
if (context.size() == 0) {
if (name == "skin") {
@@ -227,7 +184,7 @@ bool xStartElem(const std::string &name, std::map<std::string,std::string> &attr
bool xCharData(const std::string &text) {
int start = 0, end = text.length() - 1;
- Dprintf("char data before: %s\n", text.c_str());
+ //Dprintf("char data before: %s\n", text.c_str());
while (text[start] == '\012' || text[start] == '\015' || text[start] == ' ' || text[start] == '\t')
++start;
@@ -235,22 +192,22 @@ bool xCharData(const std::string &text) {
while (text[end] == '\012' || text[end] == '\015' || text[end] == ' ' || text[end] == '\t')
--end;
- Dprintf("char data after: %s\n", text.substr(start, end - start + 1).c_str());
+ //Dprintf("char data after: %s\n", text.substr(start, end - start + 1).c_str());
if (end - start + 1 > 0) {
- Dprintf("context: %s\n", context[context.size() - 1].c_str());
+ //Dprintf("context: %s\n", context[context.size() - 1].c_str());
if (context[context.size() - 1] == "text"
|| context[context.size() - 1] == "scrolltext") {
if (!object->mText.Parse(text.substr(start, end - start + 1)))
return false;
} else
- esyslog(MSG_BADCDATA);
+ esyslog("ERROR: Bad character data");
}
return true;
}
bool xEndElem(const std::string &name) {
- Dprintf("end element: %s\n", name.c_str());
+ //Dprintf("end element: %s\n", name.c_str());
if (context[context.size() - 1] == name) {
if (name == "display") {
skin->mDisplays[display->Type()] = display;
@@ -258,7 +215,7 @@ bool xEndElem(const std::string &name) {
}
else if (object != NULL || parent != NULL) {
if (object == NULL) {
- Dprintf("rotating parent to object\n");
+ //Dprintf("rotating parent to object\n");
object = parent;
parent = NULL;
}
@@ -275,7 +232,7 @@ bool xEndElem(const std::string &name) {
}
if (parent != NULL) {
- Dprintf("pushing to parent\n");
+ //Dprintf("pushing to parent\n");
if (parent->mObjects == NULL)
parent->mObjects = new cxObjects();
parent->mObjects->push_back(object);
diff --git a/xml/string.c b/xml/string.c
index 051a003..269aa0f 100644
--- a/xml/string.c
+++ b/xml/string.c
@@ -91,6 +91,7 @@ bool cxString::Parse(const std::string &Text) {
int pos = -1;
txToken &lastToken = mTokens[mTokens.size() - 1];
+ Dprintf("assigning attrib: %.*s\n", ptr-last, last);
lastToken.Attrib.assign(last, ptr - last);
while ((pos = lastToken.Attrib.find('\\', pos + 1)) != -1) {
switch (lastToken.Attrib[pos + 1]) {
diff --git a/xml/type.c b/xml/type.c
index d311b30..0cb5c9a 100644
--- a/xml/type.c
+++ b/xml/type.c
@@ -7,11 +7,12 @@
#include <stdio.h>
const std::string &cxType::String(void) {
- static char buffer[50];
if (mType == number) {
- snprintf(buffer, sizeof(buffer), "%d", mNumber);
+ char *buffer;
+ asprintf(&buffer, "%d", mNumber);
mString = buffer;
mType = string;
+ free(buffer);
} else if (mType == boolean) {
mString = mNumber ? cxFunction::True : cxFunction::False;
mType = string;
diff --git a/xml/type.h b/xml/type.h
index 1b1113c..14e7cca 100644
--- a/xml/type.h
+++ b/xml/type.h
@@ -5,6 +5,7 @@
#ifndef VDR_TEXT2SKIN_XML_TYPE_H
#define VDR_TEXT2SKIN_XML_TYPE_H
+#include <stdio.h>
#include <string>
class cxType {
@@ -26,6 +27,7 @@ public:
cxType(int Number): mType(number), mNumber(Number) {}
cxType(time_t Number): mType(number), mNumber(Number) {}
cxType(bool Value): mType(boolean), mNumber(Value ? 1 : 0) {}
+ cxType(const cxType &Src): mType(Src.mType), mString(Src.mString), mNumber(Src.mNumber) {}
const std::string &String(void);
int Number(void) const;
diff --git a/xml/xml.c b/xml/xml.c
index 07dae8c..ebf7d00 100644
--- a/xml/xml.c
+++ b/xml/xml.c
@@ -16,6 +16,9 @@ enum {
LOOK4START, // looking for first element start
LOOK4TAG, // looking for element tag
INTAG, // reading tag
+ INCOMMENT, // reading comment
+ LOOK4CEND1, // looking for second '-' in -->
+ LOOK4CEND2, // looking for '>' in -->
LOOK4ATTRN, // looking for attr name, > or /
INATTRN, // reading attr name
LOOK4ATTRV, // looking for attr value
@@ -149,7 +152,7 @@ XML::readChar(int c) {
}
break;
} else {
- if (c == '?' || c == '!') {
+ if (c == '?') {
skipping = true;
break;
}
@@ -159,6 +162,8 @@ XML::readChar(int c) {
state = INTAG;
} else if (c == '/') {
state = LOOK4CLOSETAG;
+ } else if (c == '!') {
+ state = INCOMMENT;
} else if (!isspace(c)) {
if (parseerrorcb) {
parseerrorcb(linenr, "Bogus tag char", c);
@@ -183,6 +188,31 @@ XML::readChar(int c) {
}
break;
+ // reading comment
+ case INCOMMENT:
+ if (c == '-') {
+ state = LOOK4CEND1;
+ }
+ break;
+
+ // looking for second '-' in "-->"
+ case LOOK4CEND1:
+ if (c == '-') {
+ state = LOOK4CEND2;
+ } else {
+ state = INCOMMENT;
+ }
+ break;
+
+ // looking for '>' in "-->"
+ case LOOK4CEND2:
+ if (c == '>') {
+ state = LOOK4START;
+ } else if (c != '-') {
+ state = INCOMMENT;
+ }
+ break;
+
// looking for attr name, > or /
case LOOK4ATTRN:
if (c == '>') {