summaryrefslogtreecommitdiff
path: root/xbm.c
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-12-07 02:53:31 -0800
committerAnas Nashif <anas.nashif@intel.com>2012-12-07 02:53:31 -0800
commitcbb6286cb92020dd7ae88798ed831ed76fd2130e (patch)
tree782a01c00d5e064aa67ea3f9241a8ef1de1060c6 /xbm.c
downloadlinks-cbb6286cb92020dd7ae88798ed831ed76fd2130e.tar.gz
links-cbb6286cb92020dd7ae88798ed831ed76fd2130e.tar.bz2
links-cbb6286cb92020dd7ae88798ed831ed76fd2130e.zip
Imported Upstream version 2.6upstream/2.6upstream
Diffstat (limited to 'xbm.c')
-rw-r--r--xbm.c303
1 files changed, 303 insertions, 0 deletions
diff --git a/xbm.c b/xbm.c
new file mode 100644
index 0000000..edc6e1c
--- /dev/null
+++ b/xbm.c
@@ -0,0 +1,303 @@
+/* xbm.c
+ * portable bitmap format (xbm) decoder
+ * (c) 2002 Petr 'Brain' Kulhavy
+ * This file is a part of the Links program, released under GPL
+ */
+
+#include "cfg.h"
+
+#ifdef G
+
+#include "links.h"
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+
+#define XBM_BUFFER_LEN 1024
+
+#ifdef min
+#undef min
+#endif
+#ifdef max
+#undef max
+#endif
+#define min(a,b) (a<b?a:b)
+#define max(a,b) (a>b?a:b)
+
+struct xbm_decoder{
+ int width, height; /* rozmery obrazku */
+ int partnum; /* buffer skoncil uprostred cisla */
+ int *numdest; /* kam se ma ukladat to cislo kdyz je partnum */
+ int in_data_block; /* jsme v bloku dat (uz jsme precetli otviraci slozenou zavorku) */
+ int image_pos; /* pixelova pozice v cimg->buffer */
+ int pixels; /* velikost cimg->buffer v pixelech */
+ int state; /* stav automatu na zrani komentaru */
+ int actual_eight; /* aktualni cislo, ktere se ma putnout do cimg */
+ int line_pos; /* aktualni pozice pixelu na radce (kolik pixelu v cimg->buffer je platnych na momentalne zpracovavane radce) */
+ unsigned char barvicky[6]; /* 0-2 background, 3-5 foreground */
+/*
+ * stavy:
+ * 0 - mimo komentar
+ * 1 - za 1. lomitkem
+ * 2 - za 1. lomitkem a hvezdickou
+ * 3 - za 2. hvezdickou
+ */
+ int buffer_pos; /* delka platnych dat v bufferu */
+ unsigned char buffer[XBM_BUFFER_LEN];
+};
+
+
+static unsigned char *my_memmem(unsigned char *h, int hl, unsigned char *n, int nl)
+{
+ for (;hl>=nl;hl--,h++)
+ if (*h==*n&&!memcmp(h,n,nl))return h;
+ return NULL;
+}
+
+
+void xbm_start(struct cached_image *cimg)
+{
+ struct xbm_decoder *deco;
+ unsigned short r,g,b;
+
+ deco=mem_alloc(sizeof(struct xbm_decoder));
+ cimg->decoder=deco;
+ deco->state=0;
+ deco->width=-1;
+ deco->height=-1;
+ deco->buffer_pos=0;
+ deco->partnum=0;
+ deco->in_data_block=0;
+
+ round_color_sRGB_to_48(&r,&g,&b,cimg->background_color);
+ deco->barvicky[0]=apply_gamma_single_16_to_8(r,display_red_gamma);
+ deco->barvicky[1]=apply_gamma_single_16_to_8(g,display_green_gamma);
+ deco->barvicky[2]=apply_gamma_single_16_to_8(b,display_blue_gamma);
+
+ round_color_sRGB_to_48(&r,&g,&b,get_foreground(cimg->background_color));
+ deco->barvicky[3]=apply_gamma_single_16_to_8(r,display_red_gamma);
+ deco->barvicky[4]=apply_gamma_single_16_to_8(g,display_green_gamma);
+ deco->barvicky[5]=apply_gamma_single_16_to_8(b,display_blue_gamma);
+
+
+}
+
+/* vrati cislo, nebo -1, kdyz to neni cislo, a nastavi p a l na posledni necislici */
+static inline int xbm_read_num(unsigned char **p,int *l,int *partnum,int *digits, int *base)
+{
+ static int a=-1;
+ static int b=10;
+ static int d=0;
+ int retval;
+ int was_partnum=*partnum;
+ *partnum=0;
+
+ dalsi_runda:
+ if (!(*l))return a;
+ **p=tolower(**p);
+ if (!was_partnum&&b==10&&((**p)<'0'||(**p)>'9'))goto smitec; /* tohle neni cislo, to si strc nekam... */
+ if (b==16&&((**p)<'a'||(**p>'f'))&&((**p)<'0'||(**p)>'9'))goto smitec;
+ if (a==-1)a=0;
+ for (;*l&&(((**p)>='0'&&(**p)<='9')||(b==16&&(**p)>='a'&&(**p)<='f'));(*l)--,(*p)++){d++;a*=b;a+=((**p)>='a'?10+(**p)-'a':(**p)-'0');}
+ if (b==10&&!a&&(*l)&&((**p)|32)=='x'){b=16;d=0;(*p)++;(*l)--;if (!*l)*partnum=1;goto dalsi_runda;}
+ smitec:
+ retval=a;
+ if (!*l)*partnum=1;
+ else a=-1,*base=b,b=10,*digits=d,d=0;
+ return retval;
+}
+
+
+static inline void xbm_skip_space_tab(unsigned char **p, int *l)
+{
+ for (;*l&&(**p==' '||**p==9);(*l)--,(*p)++)
+ ;
+}
+
+
+static inline void xbm_skip_whitespace(unsigned char **p, int *l)
+{
+ for (;*l&&((**p)>'9'||(**p)<'0');(*l)--,(*p)++)
+ ;
+}
+
+
+static inline void put_eight(struct cached_image *cimg,int bits)
+{
+ struct xbm_decoder *deco=(struct xbm_decoder *)cimg->decoder;
+ int ten_napis_v_s3_nekecal;
+
+ for (ten_napis_v_s3_nekecal=0;ten_napis_v_s3_nekecal<bits&&deco->image_pos<deco->pixels&&deco->line_pos<cimg->width;ten_napis_v_s3_nekecal++,deco->image_pos++,deco->line_pos++)
+ {
+ memcpy(cimg->buffer+deco->image_pos*3,deco->barvicky+((deco->actual_eight)&1)*3,3);
+ deco->actual_eight>>=1;
+ cimg->rows_added=1;
+ }
+ if (deco->line_pos==cimg->width)
+ deco->line_pos=0,deco->actual_eight=0;
+}
+
+
+/* opravdovy dekoder xbm, data jsou bez komentaru */
+/* length is always !=NULL */
+static int xbm_decode(struct cached_image *cimg, unsigned char *data, int length)
+{
+ struct xbm_decoder *deco=(struct xbm_decoder *)cimg->decoder;
+ /* okurky v decu ;-) */
+ int a;
+ int must_return=0;
+
+restart_again:
+ if (must_return&&!length)return 0;
+ must_return=0;
+ a=min(length,XBM_BUFFER_LEN-deco->buffer_pos);
+ memcpy(deco->buffer+deco->buffer_pos,data,a);
+ length-=a;
+ deco->buffer_pos+=a;
+ if (!deco->buffer_pos)return 0; /* z toho nic plodnyho nevznikne */
+ data+=a;
+ if (!deco->in_data_block&&deco->partnum)
+ {
+ unsigned char *p;
+ int a;
+ int b,d;
+ p=deco->buffer;
+ a=deco->buffer_pos;
+ *(deco->numdest)=xbm_read_num(&p,&a,&(deco->partnum),&d,&b);
+ /* p i a ukazuje na 1. neciselnej znak (at uz za mezerama bylo cislo nebo nebylo) */
+ memmove(deco->buffer,p,a);
+ deco->buffer_pos=a;
+ if (deco->partnum){must_return=1;goto restart_again;} /* zase konec bufferu */
+ }
+ if (deco->width<0||deco->height<0) /* decoding header */
+ {
+ unsigned char *p,*q;
+ int *d;
+ int a;
+ int base, digits;
+
+ p=my_memmem(deco->buffer,deco->buffer_pos,"width",5);
+ q=my_memmem(deco->buffer,deco->buffer_pos,"height",6);
+
+ if (!p&&!q) /* sezereme zacatek */
+ {
+ int a=deco->buffer_pos>5?deco->buffer_pos:0; /* nesmime ukrast kus width/height */
+ memmove(deco->buffer,deco->buffer+deco->buffer_pos-a,deco->buffer_pos-a); /* sezereme to pred width/height */
+ deco->buffer_pos-=a;
+ must_return=1;
+ goto restart_again;
+ }
+
+ p=p&&q?min(p,q):max(p,q); /* bereme vetsi, protoze ten 2. je NULL */
+ memmove(deco->buffer,p,(deco->buffer_pos)+(deco->buffer)-p); /* sezereme to pred width/height */
+ deco->buffer_pos-=p-deco->buffer;
+ /* deco->buffer zacina height/width */
+ if (deco->buffer[0]=='w'){p=deco->buffer+5;d=&(deco->width);}
+ else {p=deco->buffer+6;d=&(deco->height);}
+
+ a=deco->buffer_pos+deco->buffer-p;
+ xbm_skip_space_tab(&p,&a);
+ if (!a){must_return=1;goto restart_again;} /* v bufferu je: width/height, whitespace, konec */
+ *d=xbm_read_num(&p,&a,&(deco->partnum),&digits, &base);
+ if (deco->partnum)deco->numdest=d,must_return=1;
+ /* p i a ukazuje na 1. neciselnej znak (at uz za mezerama bylo cislo nebo nebylo) */
+ memmove(deco->buffer,p,a);
+ deco->buffer_pos=a;
+ goto restart_again;
+ }
+ else /* decoding data */
+ {
+ unsigned char *p;
+ int a;
+ int d=0,b=10;
+ if (!deco->in_data_block)
+ {
+ p=memchr(deco->buffer,'{',deco->buffer_pos);
+ if (!p){deco->buffer_pos=0;must_return=1;goto restart_again;} /* sezerem celej blok a cekame na zavorku */
+
+ cimg->width=deco->width;
+ cimg->height=deco->height;
+ cimg->buffer_bytes_per_pixel=3;
+ cimg->red_gamma=display_red_gamma;
+ cimg->green_gamma=display_green_gamma;
+ cimg->blue_gamma=display_blue_gamma;
+ cimg->strip_optimized=0;
+ if (header_dimensions_known(cimg)) {img_end(cimg);return 1;}
+
+ deco->in_data_block=1;
+ p++;
+ memmove(deco->buffer,p,deco->buffer_pos+deco->buffer-p); /* sezereme to pred width/height */
+ deco->buffer_pos-=p-deco->buffer;
+ deco->image_pos=0;
+ deco->pixels=deco->width*deco->height;
+ deco->line_pos=0;
+ }
+ p=deco->buffer;
+ a=deco->buffer_pos;
+ if (!deco->partnum) xbm_skip_whitespace(&p,&a);
+ if (!a){must_return=1; goto restart_again;}
+ deco->actual_eight=xbm_read_num(&p,&a,&(deco->partnum),&d,&b);
+ memmove(deco->buffer,p,a);
+ deco->buffer_pos=a;
+ if (deco->partnum)must_return=1;
+ else put_eight(cimg,(b==16&&d>2)||(b==10&&deco->actual_eight>255)?16:8);
+ if (deco->image_pos>=deco->pixels) {img_end(cimg);return 1;}
+ goto restart_again;
+
+ }
+}
+
+
+/* skip comments and call real decoding function */
+void xbm_restart(struct cached_image *cimg, unsigned char *data, int length)
+{
+ struct xbm_decoder *deco=(struct xbm_decoder*)cimg->decoder;
+
+cycle_again:
+
+ if (!length)return;
+ switch(deco->state)
+ {
+ case 0: /* mimo komentar */
+ {
+ unsigned char *p;
+ p=memchr(data,'/',length);
+ if (!p){xbm_decode(cimg, data, length);return;}
+ if (xbm_decode(cimg, data, p-data)) return;
+ length-=p-data+1;
+ data=p+1; /* preskocim lomitko */
+ deco->state=1;
+ goto cycle_again;
+ }
+
+ case 1: /* za 1. lomitkem */
+ {
+ if (*data=='*'){deco->state=2;data++;length--;goto cycle_again;} /* zacal komentar */
+ if (xbm_decode(cimg, "/", 1)) return;
+ deco->state=0; /* to nebyl komentar */
+ goto cycle_again;
+ }
+
+ case 2: /* za lomeno hvezdicka (uvnitr komentare) */
+ {
+ unsigned char *p;
+ p=memchr(data,'*',length);
+ if (!p)return; /* furt komentar */
+ length-=p-data+1;
+ data=p+1; /* preskocim hvezdicku */
+ deco->state=3;
+ goto cycle_again;
+ }
+
+ case 3: /* za 2. hvezdickou */
+ {
+ if (*data=='/'){data++;length--;deco->state=0;goto cycle_again;} /* skoncil komentar */
+ deco->state=2;
+ data++;
+ length--;
+ goto cycle_again;
+ }
+ }
+}
+#endif /* G */