Annotation of parser3/src/classes/image.C, revision 1.20
1.1 paf 1: /** @file
2: Parser: @b image parser class.
3:
1.16 paf 4: Copyright(c) 2001 ArtLebedev Group(http://www.artlebedev.com)
1.1 paf 5:
1.16 paf 6: Author: Alexander Petrosyan <paf@design.ru>(http://design.ru/paf)
1.1 paf 7:
1.20 ! paf 8: $Id: image.C,v 1.19 2001/04/17 19:31:06 paf Exp $
1.1 paf 9: */
10:
11: #include "pa_config_includes.h"
12:
1.8 paf 13: #include "gif.h"
1.6 paf 14:
1.1 paf 15: #include "pa_common.h"
16: #include "pa_request.h"
17: #include "pa_vfile.h"
18: #include "pa_vimage.h"
19:
20: // global var
21:
22: VStateless_class *image_class;
23:
24: // helpers
25:
26: class Measure_reader {
27: public:
1.16 paf 28: enum { READ_CHUNK_SIZE=0x400 };// 1K
29: typedef size_t(*Func)(void *& buf, size_t limit, void *info);
1.1 paf 30:
31: Measure_reader(Func afunc, void *ainfo) :
32: func(afunc), info(ainfo),
33: chunk(0), offset(0), size(0) {
34: }
35:
36: size_t read(unsigned char *& buf, size_t limit) {
1.3 paf 37: if(offset+limit>size) // nothing left
38: if(offset==0 || limit==1) { // only one-byte continuations allowed
39: size=(*func)(chunk, READ_CHUNK_SIZE, info);
40: offset=0;
41: } else
1.16 paf 42: return 0;// as if EOF
1.1 paf 43: if(!size) // EOF
44: return 0;
45:
46: // something left
47: size_t read_size=min(offset+limit, size)-offset;
48: buf=((unsigned char *)chunk)+offset;
49: offset+=read_size;
50: return read_size;
51: }
52:
53: private:
54: Func func;
55: void *info;
56:
57: void *chunk;
58: size_t offset;
59: size_t size;
60: };
61:
62: // GIF
63: struct GIF_Header {
1.16 paf 64: char type[3]; // 'GIF'
1.1 paf 65: char version[3];
66: unsigned char width[2];
67: unsigned char height[2];
68: char dif;
69: char fonColor;
70: char nulls;
71: };
72:
73: // JPEG
74: struct JFIF_Header {
1.16 paf 75: char length[2]; // length of JFIF segment marker
76: char identifier[5]; // JFIF identifier
77: char version[2]; // version
78: char units; // units X of Y pixel density
79: char xdensity[2]; // X pixel density
80: char ydensity[2]; // X pixel density
81: char xthumbnails; // width of thumbnails
82: char ythumbnails; // height of thumbnails
83: char reserved; // reserved
1.1 paf 84: };
85: struct JPG_Frame {
1.16 paf 86: char length[2]; // length of image marker
87: char data; // data precision of bits/sample
88: char height[2]; // image height
89: char width[2]; // image width
90: char numComponents; // number of color components
1.1 paf 91: };
92:
93: //
94:
95: inline short bytes_to_int(unsigned char HI, unsigned char LO) {
1.16 paf 96: return(short)((HI<<8) + LO);
1.1 paf 97: }
98:
99: void measure_gif(Pool& pool, const String *origin_string,
100: Measure_reader& reader, int& width, int& height) {
101:
102: unsigned char *buf;
103: const int head_size=sizeof(GIF_Header);
104: if(reader.read(buf, head_size)<head_size)
105: PTHROW(0, 0,
106: origin_string,
107: "broken GIF header - file size is less then %d bytes", head_size);
108:
109: GIF_Header& screenD=*reinterpret_cast<GIF_Header *>(buf);
110: if(strncmp(screenD.type, "GIF", 3)!=0)
111: PTHROW(0, 0,
112: origin_string,
113: "bad image file - GIF signature not found");
114:
115: width=bytes_to_int(screenD.width[1], screenD.width[0]);
116: height=bytes_to_int(screenD.height[1], screenD.height[0]);
117: }
118:
119: void measure_jpeg(Pool& pool, const String *origin_string,
120: Measure_reader& reader, int& width, int& height) {
1.2 paf 121: // JFIF format markers
122: const unsigned char SOI=0xD8;
123: const unsigned char EOI=0xD9;
124: const unsigned char APP0=0xE0;
125: const unsigned char SOF0=0xC0;
126: const unsigned char SOF2=0xC2;
127: const unsigned char COM=0xFE;
128:
1.1 paf 129: unsigned char *screenD_buf;
1.3 paf 130: unsigned char *h_buf=0;
1.1 paf 131:
132: bool flag=false;
133:
134: unsigned char *prefix;
1.18 paf 135: const size_t prefix_size=2;
1.1 paf 136: if(reader.read(prefix, prefix_size)<prefix_size)
137: PTHROW(0, 0,
138: origin_string,
139: "broken JPEG file - size is less then %d bytes", prefix_size);
140:
141: if(((unsigned char *)prefix)[1]!=SOI)
142: PTHROW(0, 0,
143: origin_string,
144: "broken JPEG file - second byte of header is not 0x%02X", SOI);
145:
146: unsigned char zero=0;
147: unsigned char *marker=&zero;
148:
149: do {
150: while((*marker)!=0xFF)
151: if(reader.read(marker, sizeof(char))<=0) break;
152: if(reader.read(marker, sizeof(char))<=0) break;
153: switch(*marker) {
154: case EOI:
155: marker=&zero;
156: break;
157: case APP0:
158: if(!flag) {
159: flag=true;
160: if(reader.read(screenD_buf, sizeof(JFIF_Header)) < sizeof(JFIF_Header))
161: break;
162: JFIF_Header& screenD=*reinterpret_cast<JFIF_Header *>(screenD_buf);
163: if((bytes_to_int(screenD.length[0], screenD.length[1]) < 16) ||
1.2 paf 164: strcasecmp(screenD.identifier, "JFIF")) flag=false;
1.1 paf 165: }
166: break;
167: case SOF0:
168: case SOF2:
169: if(reader.read(h_buf, sizeof(JPG_Frame))<sizeof(JPG_Frame))
170: flag=false;
171: break;
172: default: break;
173: }
174: } while(*marker!=EOI);
175:
1.3 paf 176: if(flag && h_buf) {
1.1 paf 177: JPG_Frame& h=*reinterpret_cast<JPG_Frame *>(h_buf);
178: width=bytes_to_int(h.width[0], h.width[1]);
179: height=bytes_to_int(h.height[0], h.height[1]);
180: } else
1.16 paf 181: PTHROW(0, 0,
182: origin_string,
1.1 paf 183: "broken JPEG file - APP0 frame not found");
184: }
185:
186: // measure center
187:
188: void measure(Pool& pool, const String& file_name,
189: Measure_reader& reader, int& width, int& height) {
190: if(const char *cext=strrchr(file_name.cstr(), '.')) {
191: cext++;
192: if(strcasecmp(cext, "GIF")==0)
193: measure_gif(pool, &file_name, reader, width, height);
194: else if(strcasecmp(cext, "JPG")==0 || strcasecmp(cext, "JPEG")==0)
195: measure_jpeg(pool, &file_name, reader, width, height);
196: else
197: PTHROW(0, 0,
198: &file_name,
199: "unhandled image file name extension '%s'", cext);
200: } else
201: PTHROW(0, 0,
202: &file_name,
203: "can not determine image type - no file name extension");
204: }
205:
206: // read from somewhere
207:
208: struct Read_mem_info {
209: unsigned char *ptr;
210: unsigned char *eof;
211: };
212: static size_t read_mem(void*& buf, size_t limit, void *info) {
213: Read_mem_info& rmi=*static_cast<Read_mem_info *>(info);
214: buf=rmi.ptr;
215: size_t read_size=min(limit, (size_t)(rmi.eof-rmi.ptr));
216: rmi.ptr+=read_size;
217: return read_size;
218: }
219:
220: struct Read_disk_info {
221: const String *file_spec;
222: size_t offset;
223: };
224: static size_t read_disk(void*& buf, size_t limit, void *info) {
225: Read_disk_info& rdi=*static_cast<Read_disk_info *>(info);
226: Pool& pool=rdi.file_spec->pool();
227:
228: size_t read_size;
229: file_read(pool, *rdi.file_spec,
230: buf, read_size,
231: false/*as_text*/,
232: true/*fail_on_read_problem*/,
233: rdi.offset, limit);
234:
235: rdi.offset+=read_size;
236: return read_size;
237: }
238:
239: // methods
240:
241: /// ^image:measure[DATA]
1.17 paf 242: static void _measure(Request& r, const String& method_name, MethodParams *params) {
1.1 paf 243: Pool& pool=r.pool();
244:
1.17 paf 245: Value& data=params->get_no_junction(0, "data must not be code");
1.1 paf 246:
1.16 paf 247: void *info;Measure_reader::Func read_func;
1.1 paf 248: Read_mem_info read_mem_info;
249: Read_disk_info read_disk_info;
250: const String *file_name;
251: if(data.is_string()) {
252: file_name=data.get_string();
253: read_disk_info.file_spec=&r.absolute(*file_name);
254: read_disk_info.offset=0;
1.16 paf 255: info=&read_disk_info;read_func=read_disk;
1.1 paf 256: } else {
257: const VFile& vfile=*data.as_vfile();
258: file_name=&static_cast<Value *>(vfile.fields().get(*name_name))->as_string();
259: read_mem_info.ptr=(unsigned char *)vfile.value_ptr();
260: read_mem_info.eof=read_mem_info.ptr+vfile.value_size();
1.16 paf 261: info=&read_mem_info;read_func=read_mem;
1.1 paf 262: }
263:
264: Measure_reader reader(read_func, info);
265: int width, height;
266: measure(pool, *file_name, reader, width, height);
267:
1.6 paf 268: static_cast<VImage *>(r.self)->set(file_name, width, height);
1.1 paf 269: }
270:
1.4 paf 271: struct Attrib_info {
272: String *tag;
273: Hash *skip;
274: };
1.3 paf 275: static void append_attrib_pair(const Hash::Key& key, Hash::Val *val, void *info) {
1.4 paf 276: Attrib_info& ai=*static_cast<Attrib_info *>(info);
277:
278: if(ai.skip && ai.skip->get(key))
279: return;
280:
1.3 paf 281: Value& value=*static_cast<Value *>(val);
282: // src="a.gif" width=123 ismap[=-1]
1.4 paf 283: *ai.tag << " " << key;
1.6 paf 284: if(value.is_string() || value.as_double()>=0)
285: *ai.tag << "=\"" << value.as_string() << "\"";
1.3 paf 286: }
287: /// ^image.html[]
288: /// ^image.html[hash]
1.17 paf 289: static void _html(Request& r, const String& method_name, MethodParams *params) {
1.3 paf 290: Pool& pool=r.pool();
291:
292: String tag(pool);
293: tag << "<img";
1.4 paf 294:
1.18 paf 295: const Hash& fields=static_cast<VImage *>(r.self)->fields();
1.5 paf 296: Hash *attribs=0;
1.4 paf 297:
1.11 paf 298: if(params->size())
1.17 paf 299: if(attribs=params->get(0).get_hash()) {
1.4 paf 300: Attrib_info attrib_info={&tag, 0};
1.5 paf 301: attribs->for_each(append_attrib_pair, &attrib_info);
1.4 paf 302: } else
1.16 paf 303: PTHROW(0, 0,
304: &method_name,
1.5 paf 305: "attributes must be must be hash");
1.4 paf 306:
1.5 paf 307: Attrib_info attrib_info={&tag, attribs};
1.4 paf 308: fields.for_each(append_attrib_pair, &attrib_info);
1.6 paf 309: tag << " />";
1.3 paf 310: r.write_pass_lang(tag);
311: }
1.8 paf 312:
1.16 paf 313: static gdImage *load(Request& r, const String& method_name,
314: const String& file_name){
315: Pool& pool=r.pool();
316:
317: const char *file_name_cstr=r.absolute(file_name).cstr(String::UL_FILE_NAME);
318: if(FILE *f=fopen(file_name_cstr, "rb")) {
319: gdImage& image=*new(pool) gdImage(pool);
320: image.CreateFromGif(f);
321: fclose(f);
322: return ℑ
323: } else {
324: PTHROW(0, 0,
325: &method_name,
326: "can not open '%s'", file_name_cstr);
327: return 0;
328: }
329: }
330:
331:
1.6 paf 332: /// ^image.load[background.gif]
1.17 paf 333: static void _load(Request& r, const String& method_name, MethodParams *params) {
1.6 paf 334: Pool& pool=r.pool();
335:
1.17 paf 336: Value& vfile_name=params->get_no_junction(0, "file name must not be code");
1.6 paf 337: const String& file_name=vfile_name.as_string();
338:
1.16 paf 339: gdImage& image=*load(r, method_name, file_name);
340: int width=image.SX();
341: int height=image.SY();
342: static_cast<VImage *>(r.self)->set(&file_name, width, height, &image);
1.6 paf 343: }
344:
345: /// ^image.create[width;height] bgcolor=white
346: /// ^image.create[width;height;bgcolor]
1.17 paf 347: static void _create(Request& r, const String& method_name, MethodParams *params) {
1.6 paf 348: Pool& pool=r.pool();
349:
1.17 paf 350: int width=(int)r.process(params->get(0)).as_double();
351: int height=(int)r.process(params->get(1)).as_double();
1.8 paf 352: int bgcolor_value=0xffFFff;
1.6 paf 353: if(params->size()>2)
1.17 paf 354: bgcolor_value=(int)r.process(params->get(2)).as_double();
1.15 paf 355: gdImage& image=*new(pool) gdImage(pool);
356: image.Create(width, height);
357: image.FilledRectangle(0, 0, width-1, height-1, image.Color(bgcolor_value));
358: static_cast<VImage *>(r.self)->set(0, width, height, &image);
1.6 paf 359: }
360:
361: /// ^image.gif[]
1.17 paf 362: static void _gif(Request& r, const String& method_name, MethodParams *params) {
1.6 paf 363: Pool& pool=r.pool();
364:
1.9 paf 365: gdImage *image=static_cast<VImage *>(r.self)->image;
1.8 paf 366: if(!image)
1.16 paf 367: PTHROW(0, 0,
368: &method_name,
1.12 paf 369: "does not contain an image");
1.6 paf 370:
371: // could _ but don't thing it's wise to use $image.src for vfile.name
1.10 paf 372:
1.16 paf 373: String out(pool); image->Gif(out);
1.6 paf 374:
375: VFile& vfile=*new(pool) VFile(pool);
376: String& image_gif=*new(pool) String(pool, "image/gif");
1.20 ! paf 377: vfile.set(false/*not tainted*/,
! 378: out.cstr(String::UL_AS_IS), out.size(), 0, &image_gif);
1.6 paf 379:
380: r.write_no_lang(vfile);
381: }
382:
1.12 paf 383: /// ^image.line(x0;y0;x1;y1;color)
1.17 paf 384: static void _line(Request& r, const String& method_name, MethodParams *params) {
1.12 paf 385: Pool& pool=r.pool();
386:
387: gdImage *image=static_cast<VImage *>(r.self)->image;
388: if(!image)
1.16 paf 389: PTHROW(0, 0,
390: &method_name,
1.12 paf 391: "does not contain an image");
392:
393: image->Line(
1.17 paf 394: (int)r.process(params->get(0)).as_double(),
395: (int)r.process(params->get(1)).as_double(),
396: (int)r.process(params->get(2)).as_double(),
397: (int)r.process(params->get(3)).as_double(),
398: image->Color((int)r.process(params->get(4)).as_double()));
1.13 paf 399: }
400:
401: /// ^image.fill(x;y;color)
1.17 paf 402: static void _fill(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 403: Pool& pool=r.pool();
404:
405: gdImage *image=static_cast<VImage *>(r.self)->image;
406: if(!image)
1.16 paf 407: PTHROW(0, 0,
408: &method_name,
1.13 paf 409: "does not contain an image");
1.12 paf 410:
1.13 paf 411: image->Fill(
1.17 paf 412: (int)r.process(params->get(0)).as_double(),
413: (int)r.process(params->get(1)).as_double(),
414: image->Color((int)r.process(params->get(2)).as_double()));
1.13 paf 415: }
416:
417: /// ^image.rectangle(x0;y0;x1;y1;color)
1.17 paf 418: static void _rectangle(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 419: Pool& pool=r.pool();
420:
421: gdImage *image=static_cast<VImage *>(r.self)->image;
422: if(!image)
1.16 paf 423: PTHROW(0, 0,
424: &method_name,
1.13 paf 425: "does not contain an image");
426:
427: image->Rectangle(
1.17 paf 428: (int)r.process(params->get(0)).as_double(),
429: (int)r.process(params->get(1)).as_double(),
430: (int)r.process(params->get(2)).as_double(),
431: (int)r.process(params->get(3)).as_double(),
432: image->Color((int)r.process(params->get(4)).as_double()));
1.13 paf 433: }
434:
435: /// ^image.bar(x0;y0;x1;y1;color)
1.17 paf 436: static void _bar(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 437: Pool& pool=r.pool();
438:
439: gdImage *image=static_cast<VImage *>(r.self)->image;
440: if(!image)
1.16 paf 441: PTHROW(0, 0,
442: &method_name,
1.13 paf 443: "does not contain an image");
444:
445: image->FilledRectangle(
1.17 paf 446: (int)r.process(params->get(0)).as_double(),
447: (int)r.process(params->get(1)).as_double(),
448: (int)r.process(params->get(2)).as_double(),
449: (int)r.process(params->get(3)).as_double(),
450: image->Color((int)r.process(params->get(4)).as_double()));
1.13 paf 451: }
452:
453: /// ^image.replace(color-source;color-dest)(x;y)... point coord pairs
1.17 paf 454: static void _replace(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 455: Pool& pool=r.pool();
456:
457: gdImage *image=static_cast<VImage *>(r.self)->image;
458: if(!image)
1.16 paf 459: PTHROW(0, 0,
460: &method_name,
1.13 paf 461: "does not contain an image");
462:
463: if((params->size()-2)%2) // I see your thoughts, but that's more readable
1.16 paf 464: PTHROW(0, 0,
465: &method_name,
1.13 paf 466: "y coordinate missing");
467:
468: int n=(params->size()-2)/2;
469:
470: gdImage::Point *p=(gdImage::Point *)pool.malloc(sizeof(gdImage::Point)*n);
471: for(int i=0; i<n; i++) {
1.17 paf 472: p[i].x=(int)r.process(params->get(2+i*2+0)).as_double();
473: p[i].y=(int)r.process(params->get(2+i*2+1)).as_double();
1.13 paf 474: }
1.16 paf 475: image->FilledPolygonReplaceColor(p, n,
1.17 paf 476: image->Color((int)r.process(params->get(0)).as_double()), // src color
477: image->Color((int)r.process(params->get(1)).as_double()));// dest color
1.13 paf 478: }
479:
480: /// ^image.polygon(color)(x;y)... point coord pairs
1.17 paf 481: static void _polygon(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 482: Pool& pool=r.pool();
483:
484: gdImage *image=static_cast<VImage *>(r.self)->image;
485: if(!image)
1.16 paf 486: PTHROW(0, 0,
487: &method_name,
1.13 paf 488: "does not contain an image");
489:
490: if((params->size()-1)%2) // [I see..] see now?
1.16 paf 491: PTHROW(0, 0,
492: &method_name,
1.13 paf 493: "y coordinate missing");
494:
495: int n=(params->size()-1)/2;
496:
497: gdImage::Point *p=(gdImage::Point *)pool.malloc(sizeof(gdImage::Point)*n);
498: for(int i=0; i<n; i++) {
1.17 paf 499: p[i].x=(int)r.process(params->get(1+i*2+0)).as_double();
500: p[i].y=(int)r.process(params->get(1+i*2+1)).as_double();
1.13 paf 501: }
1.16 paf 502: image->Polygon(p, n,
1.17 paf 503: image->Color((int)r.process(params->get(0)).as_double()));
1.13 paf 504: }
505:
506: /// ^image.polybar(color)(x;y)... point coord pairs
1.17 paf 507: static void _polybar(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 508: Pool& pool=r.pool();
509:
510: gdImage *image=static_cast<VImage *>(r.self)->image;
511: if(!image)
1.16 paf 512: PTHROW(0, 0,
513: &method_name,
1.13 paf 514: "does not contain an image");
515:
516: if((params->size()-1)%2) // [I see..] see now?
1.16 paf 517: PTHROW(0, 0,
518: &method_name,
1.13 paf 519: "y coordinate missing");
520:
521: int n=(params->size()-1)/2;
522:
523: gdImage::Point *p=(gdImage::Point *)pool.malloc(sizeof(gdImage::Point)*n);
524: for(int i=0; i<n; i++) {
1.17 paf 525: p[i].x=(int)r.process(params->get(1+i*2+0)).as_double();
526: p[i].y=(int)r.process(params->get(1+i*2+1)).as_double();
1.13 paf 527: }
1.16 paf 528: image->FilledPolygon(p, n,
1.17 paf 529: image->Color((int)r.process(params->get(0)).as_double()));
1.12 paf 530: }
531:
1.16 paf 532: // font
533:
534: #define Y(y)(y+index*height+1)
535: class Font : public Pooled {
536: public:
537:
538: int height; /* Font heigth */
539: int space; /* Default char width */
540: gdImage& ifont;
541: const String& alphabet;
542:
543: Font(Pool& pool,
544: const String& aalphabet,
545: gdImage& aifont, int aheight, int aspace) : Pooled(pool),
546: alphabet(aalphabet),
547: height(aheight), space(aspace),
548: ifont(aifont) {
549: }
550:
551: /* ******************************** char ********************************** */
552:
553: int index_of(char ch) {
554: if(ch==' ') return -1;
555: return alphabet.pos(&ch, 1);
556: }
557:
558: int index_width(int index) {
559: if(index<0)
560: index=index_of('.');
561: if(index<0)
562: return 0;
563: int tr=ifont.GetTransparent();
564: for(int x=ifont.SX()-1; x>0; x--) {
565: for(int y=0; y<height-1; y++)
566: if(ifont.GetPixel(x, Y(y))!=tr)
567: return x+2;
568: }
569: return 0;
570: }
571:
572: void index_display(gdImage& image, int x, int y, int index){
573: if(index>=0)
574: ifont.Copy(image, x, y, 0, Y(0), index_width(index), height-1);
575: }
576:
577: /* ******************************** string ********************************** */
578: /*
579: int string_width(const char *cstr){
580: int result=0;
581: for(; *cstr; cstr++)
582: result+=index_width(index_of(*cstr));
583: return result;
584: }
585: */
586:
587: void string_display(gdImage& image, int x, int y, const String& s){
588: const char *cstr=s.cstr(String::UL_AS_IS);
589: if(cstr) for(; *cstr; cstr++) {
590: int index=index_of(*cstr);
591: index_display(image, x, y, index);
592: x+=space ? space : index_width(index);
593: }
594: }
595:
596: };
1.19 paf 597: /**
598: ^image.font[alPHAbet;font-file-name.gif](height)
599: ^image.font[alPHAbet;font-file-name.gif](height;width)
600: */
1.17 paf 601: static void _font(Request& r, const String& method_name, MethodParams *params) {
1.16 paf 602: Pool& pool=r.pool();
603:
1.17 paf 604: Value& valphabet=params->get_no_junction(0, "alphabet must not be code");
605: Value& file_name=params->get_no_junction(1, "file_name must not be code");
606: int height=(int)r.process(params->get(2)).as_double();
1.16 paf 607:
1.17 paf 608: int width=params->size()>3?(int)r.process(params->get(3)).as_double():0;
1.16 paf 609:
610: static_cast<VImage *>(r.self)->font=new(pool) Font(pool,
611: valphabet.as_string(),
612: *load(r, method_name, file_name.as_string()),
613: height, width);
614: }
615:
616: /// ^image.text(x;y)[text]
1.17 paf 617: static void _text(Request& r, const String& method_name, MethodParams *params) {
1.16 paf 618: Pool& pool=r.pool();
619:
1.17 paf 620: int x=(int)r.process(params->get(0)).as_double();
621: int y=(int)r.process(params->get(1)).as_double();
622: const String& s=r.process(params->get(2)).as_string();
1.16 paf 623:
624: VImage& vimage=*static_cast<VImage *>(r.self);
625: if(vimage.image)
626: if(vimage.font)
627: vimage.font->string_display(*vimage.image, x, y, s);
628: else
629: PTHROW(0, 0,
630: &method_name,
631: "set the font first");
632: else
633: PTHROW(0, 0,
634: &method_name,
635: "does not contain an image");
636: }
637:
1.1 paf 638: // initialize
639: void initialize_image_class(Pool& pool, VStateless_class& vclass) {
640: // ^image:measure[DATA]
641: vclass.add_native_method("measure", Method::CT_DYNAMIC, _measure, 1, 1);
1.3 paf 642:
643: /// ^image.html[]
644: /// ^image.html[hash]
645: vclass.add_native_method("html", Method::CT_DYNAMIC, _html, 0, 1);
1.6 paf 646:
647: /// ^image.load[background.gif]
1.8 paf 648: vclass.add_native_method("load", Method::CT_DYNAMIC, _load, 1, 1);
1.6 paf 649:
650: /// ^image.create[width;height] bgcolor=white
651: /// ^image.create[width;height;bgcolor]
652: vclass.add_native_method("create", Method::CT_DYNAMIC, _create, 2, 3);
653:
654: /// ^image.gif[]
1.14 paf 655: vclass.add_native_method("gif", Method::CT_DYNAMIC, _gif, 0, 0);
1.12 paf 656:
657: /// ^image.line(x0;y0;x1;y1;color)
658: vclass.add_native_method("line", Method::CT_DYNAMIC, _line, 5, 5);
1.13 paf 659:
660: /// ^image.fill(x;y;color)
661: vclass.add_native_method("fill", Method::CT_DYNAMIC, _fill, 3, 3);
662:
663: /// ^image.rectangle(x0;y0;x1;y1;color)
664: vclass.add_native_method("rectangle", Method::CT_DYNAMIC, _rectangle, 5, 5);
665:
666: /// ^image.bar(x0;y0;x1;y1;color)
667: vclass.add_native_method("bar", Method::CT_DYNAMIC, _bar, 5, 5);
668:
669: /// ^image.replace(color-source;color-dest)(x;y)... point coord pairs
670: vclass.add_native_method("replace", Method::CT_DYNAMIC, _replace, 2+3*2, 2+100*2);
671:
672: /// ^image.polygon(color)(x;y)... point coord pairs
673: vclass.add_native_method("polygon", Method::CT_DYNAMIC, _polygon, 1+3*2, 1+100*2);
674:
675: /// ^image.polybar(color)(x;y)... point coord pairs
676: vclass.add_native_method("polybar", Method::CT_DYNAMIC, _polybar, 1+3*2, 1+100*2);
677:
1.16 paf 678: /// ^image.font[alPHAbet;font-file-name.gif](height)
679: /// ^image.font[alPHAbet;font-file-name.gif](height;width)
680: vclass.add_native_method("font", Method::CT_DYNAMIC, _font, 3, 4);
681:
682: /// ^image.text(x;y)[text]
683: vclass.add_native_method("text", Method::CT_DYNAMIC, _text, 3, 3);
684:
1.1 paf 685: }
E-mail: