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