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