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