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