/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include "binding_helpers.h" #include "ui/ui.h" #include "font/font_renderer.h" #include "picture/pict_io.h" using namespace GS; using namespace GS::Script; void IterateTextParameters(HSQUIRRELVM vm, int idx, TextState &state); //------------------------------------------------------------------------------ SQInteger NewPicture(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETINT(w) __SQ_GETINT(h) __SQ_GETEND Picture *p = new Picture; if (!p || !p->AllocAs(w, h)) return sq_throwerror(vm, String::Format("Failed to allocate a new %dx%d picture.", w, h)); __SQ_RETURNSAFEPTR(p, typetag_Picture) } SQInteger LoadPicture(HSQUIRRELVM vm) { __SQ_GETSTART(1) __SQ_GETSTRING(path) Picture *p = new Picture; if (!p) return sq_throwerror(vm, "Failed to allocate picture."); if (!PictureIO::Get().Load(*p, path)) return sq_throwerror(vm, String::Format("Failed to load picture '%s'.", path)); __SQ_GETEND __SQ_RETURNSAFEPTR(p, typetag_Picture) } SQInteger PictureClone(HSQUIRRELVM vm) { __SQ_GETSINGLESAFEPTR(p, Picture, typetag_Picture) __SQ_RETURNSAFEPTR(new Picture(*p), typetag_Picture); } //------------------------------------------------------------------------------ //----------------------------------------------------------------------------- SQInteger PictureWriteText(HSQUIRRELVM vm) { __SQ_GETSTART(5) __SQ_GETSAFEPTR(p, Picture, typetag_Picture) __SQ_GETRECT(out_rect) __SQ_GETSTRING(text) __SQ_GETSAFEPTR(font, FontEx, typetag_Font) TextState state; IterateTextParameters(vm, -1, state); __SQ_GETUPDATESTACK state.font = font; iRect clip_rect = p->GetRect(); FontRenderer::Format(text, state, out_rect); FontRenderer::Compose(*p, text, state, out_rect, clip_rect); __SQ_GETEND __SQ_RETURN } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- SQInteger PictureApplyConvolution(HSQUIRRELVM vm) { Picture *pic; if (!CObject::Get(vm, -6, (void **)&pic, typetag_Picture)) return -1; if (!pic) return sq_throwerror(vm, "Invalid picture."); // Kernel size. SQInteger kw, kh; sq_getinteger(vm, -5, &kw); sq_getinteger(vm, -4, &kh); int kernel[1024]; if ((kw * kh) > 1024) return sq_throwerror(vm, "The convolution kernel is exceeding 1024 entries."); sq_pushnull(vm); // iterator for (int n = 0; n < (kw * kh); ++n) { if (SQ_FAILED(sq_next(vm, -4))) break; // Here -1 is the value and -2 is the key. SQInteger v; sq_getinteger(vm, -1, &v); kernel[n] = v; sq_pop(vm, 2); // Pops key and val before the next iteration. } sq_pop(vm, 1); // Pop the iterator. SQFloat weight; sq_getfloat(vm, -2, &weight); SQInteger pass; sq_getinteger(vm, -1, &pass); sq_pop(vm, 4); // Pop function arguments. if (!pic->ApplyConvolution(kw, kh, kernel, int(weight * 256), pass)) return sq_throwerror(vm, "Convolution filter failed."); return 0; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- SQInteger PictureLine(HSQUIRRELVM vm) { __SQ_GETSTART(6) __SQ_GETSAFEPTR(pic, Picture, typetag_Picture) __SQ_GETFLOAT(sx) __SQ_GETFLOAT(sy) __SQ_GETFLOAT(ex) __SQ_GETFLOAT(ey) __SQ_GETVECTORW(c) __SQ_GETEND fRect rect = pic->GetRect().AsFloat(); rect.ex -= 2; rect.ey -= 2; if ((rect.ex <= rect.sx) || (rect.ey < rect.sy)) return 0; pic->DrawLineHQ(sx, sy, ex, ey, c.x, c.y, c.z, c.w, &rect); return 0; } //----------------------------------------------------------------------------- //------------------------------------------------------------------------------ SQInteger PictureLoadContent(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETSAFEPTR(pic, Picture, typetag_Picture) __SQ_GETSTRING(path) bool r = PictureIO::Get().Load(*pic, path); __SQ_GETEND __SQ_RETURNBOOL(r) } SQInteger PictureSaveTGA(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETSAFEPTR(p, Picture, typetag_Picture) __SQ_GETSTRING(path) if (!PictureIO::Get().TgaSave(*p, path)) return sq_throwerror(vm, String::Format("Failed to save picture to '%s'", path)); __SQ_GETEND __SQ_RETURN } SQInteger PictureSaveJPG(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETSAFEPTR(p, Picture, typetag_Picture) __SQ_GETSTRING(path) p->Convert(PixelFormat::RGB8); if (!PictureIO::Get().Save(*p, path, "IJG")) return sq_throwerror(vm, String::Format("Failed to save picture to '%s'", path)); __SQ_GETEND __SQ_RETURN } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ SQInteger PictureGetRect(HSQUIRRELVM vm) { __SQ_GETSINGLESAFEPTR(p, Picture, typetag_Picture) iRect rect(0, 0, 0, 0); if (p) rect.Set(0, 0, p->GetWidth(), p->GetHeight()); __SQ_RETURNRECT(rect) } SQInteger PictureAlloc(HSQUIRRELVM vm) { __SQ_GETSTART(3) __SQ_GETSAFEPTR(p, Picture, typetag_Picture) __SQ_GETINT(w) __SQ_GETINT(h) __SQ_GETEND if (!p->AllocAs(w, h)) return sq_throwerror(vm, "Failed to allocate picture buffer"); __SQ_RETURN } SQInteger PictureResize(HSQUIRRELVM vm) { __SQ_GETSTART(3) __SQ_GETSAFEPTR(p, Picture, typetag_Picture) __SQ_GETINT(w) __SQ_GETINT(h) __SQ_GETEND p->Resize(w, h); __SQ_RETURN } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ SQInteger PictureSetPixel(HSQUIRRELVM vm) { __SQ_GETSTART(4) __SQ_GETSAFEPTR(p, Picture, typetag_Picture) __SQ_GETFLOAT(x) __SQ_GETFLOAT(y) __SQ_GETVECTORW(c) __SQ_GETEND p->DrawPlot(x, y, c.x, c.y, c.z, c.w); __SQ_RETURN } SQInteger PictureGetPixel(HSQUIRRELVM vm) { __SQ_GETSTART(3) __SQ_GETSAFEPTR(p, Picture, typetag_Picture) __SQ_GETFLOAT(x) __SQ_GETFLOAT(y) __SQ_GETEND Color c; p->Sample(x / p->GetWidth(), y / p->GetHeight(), c); __SQ_RETURNVECTORW(Vector4(c.x, c.y, c.z, c.w)) } SQInteger PictureFlip(HSQUIRRELVM vm) { __SQ_GETSTART(3) __SQ_GETSAFEPTR(p, Picture, typetag_Picture) __SQ_GETBOOL(h) __SQ_GETBOOL(v) __SQ_GETEND p->Flip(asbool(h), asbool(v)); __SQ_RETURN } SQInteger PictureFillLockAlpha(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETSAFEPTR(p, Picture, typetag_Picture) __SQ_GETVECTORW(c) __SQ_GETEND p->Fill(c.x, c.y, c.z, c.w, 0, true); __SQ_RETURN } SQInteger PictureFill(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETSAFEPTR(p, Picture, typetag_Picture) __SQ_GETVECTORW(c) __SQ_GETEND p->Fill(c.x, c.y, c.z, c.w); __SQ_RETURN } SQInteger PictureFillRect(HSQUIRRELVM vm) { __SQ_GETSTART(3) __SQ_GETSAFEPTR(p, Picture, typetag_Picture) __SQ_GETVECTORW(c) __SQ_GETRECT(clip_rect) __SQ_GETEND p->Fill(c.x, c.y, c.z, c.w, &clip_rect); __SQ_RETURN } SQInteger PictureBlitRect(HSQUIRRELVM vm) { __SQ_GETSTART(5) __SQ_GETSAFEPTR(src, Picture, typetag_Picture) __SQ_GETSAFEPTR(dst, Picture, typetag_Picture) __SQ_GETRECT(src_rect) __SQ_GETRECT(dst_rect) __SQ_GETINT(blend_mode) __SQ_GETEND Picture::Blit(*src, *dst, &src_rect, &dst_rect, (Picture::BlendMode)blend_mode); __SQ_RETURN } SQInteger PictureBlitRectMasked(HSQUIRRELVM vm) { __SQ_GETSTART(5) __SQ_GETSAFEPTR(src, Picture, typetag_Picture) __SQ_GETSAFEPTR(dst, Picture, typetag_Picture) __SQ_GETSAFEPTR(msk, Picture, typetag_Picture) __SQ_GETRECT(src_rect) __SQ_GETRECT(dst_rect) __SQ_GETEND Picture::BlitMask(*src, *dst, *msk, &src_rect, &dst_rect); __SQ_RETURN } SQInteger PictureBlit(HSQUIRRELVM vm) { __SQ_GETSTART(3) __SQ_GETSAFEPTR(src, Picture, typetag_Picture) __SQ_GETSAFEPTR(dst, Picture, typetag_Picture) __SQ_GETINT(blend_mode) __SQ_GETEND Picture::Blit(*src, *dst, 0, 0, (Picture::BlendMode)blend_mode); __SQ_RETURN } //------------------------------------------------------------------------------ //-------------------------------------------------------- void RegisterPictureBinding(HSQUIRRELVM vm) //-------------------------------------------------------- { /*# Topic: Picture Type: Picture #*/ /*# Section: PictureManagement Desc: Management #*/ /*# Func: NewPicture Proto: Picture:int width,int height Desc: Create a new picture, width and height are specified in pixels. Example: local picture = NewPicture() #*/ sq_register(vm, NewPicture, "NewPicture", _SC(".nn")); /*# Func: LoadPicture Proto: Picture:string path Desc: Load a picture. This function supports the following formats: Jpeg, Bmp, Targa, Png, Gif and PSD with alpha channel. Note: No caching mechanism involved, every call to this function will result in a filesystem access. Example: local picture = LoadPicture("assets/picture.png") #*/ sq_register(vm, LoadPicture, "LoadPicture", _SC(".s")); /*# Func: PictureClone Proto: Picture:Picture source Desc: Clone a picture, return the cloned picture. #*/ sq_register(vm, PictureClone, "PictureClone", _SC(".x")); /*# Section: PictureDrawing Desc: Drawing #*/ /*# Func: PictureAlloc Proto: bool:Picture,width,height Desc: Change the picture internal storage dimensions, existing data will be lost. #*/ sq_register(vm, PictureAlloc, "PictureAlloc", _SC(".xnn")); /*# Func: PictureLoadContent Proto: bool:Picture,string path Desc: Reload a picture object content from file. See: LoadPicture #*/ sq_register(vm, PictureLoadContent, "PictureLoadContent", _SC(".xs")); /*# Func: PictureSaveTGA Proto: void:Picture,string path Desc: Save a picture object to Targa. Note: Make sure that you have access to the filesystem you plan on writing to. See: SystemHasMountPoint #*/ sq_register(vm, PictureSaveTGA, "PictureSaveTGA", _SC(".xs")); /*# Func: PictureSaveJPG Proto: void:Picture,string path Desc: Save a picture object to jpg. Note: Make sure that you have access to the filesystem you plan on writing to. See: SystemHasMountPoint #*/ sq_register(vm, PictureSaveJPG, "PictureSaveJPG", _SC(".xs")); /*# Func: PictureGetRect Proto: Rect:Picture Desc: Return a picture bounding rectangle. Example: local pict = PictureLoad("picture.psd") local rect = PictureGetRect(pict) print("Picture width = " + rect.GetWidth() + ", height = " + rect.GetHeight()) #*/ sq_register(vm, PictureGetRect, "PictureGetRect", _SC(".x")); /*# Func: PictureFill Proto: void:Picture,Vector rgba Desc: Fill a picture with a solid color defined as an RGBA vector. #*/ sq_register(vm, PictureFill, "PictureFill", _SC(".xx")); /*# Func: PictureFillLockAlpha Proto: void:Picture,Vector rgba Desc: Fill a picture with a solid color defined from an RGBA vector, does not write to alpha. #*/ sq_register(vm, PictureFillLockAlpha, "PictureFillLockAlpha", _SC(".xx")); /*# Func: PictureFillRect Proto: void:Picture,Vector rgba,Rect Desc: Fill a rectangle inside a picture with a solid color defined from an RGBA vector. #*/ sq_register(vm, PictureFillRect, "PictureFillRect", _SC(".xxx")); /*# Func: PictureApplyConvolution Proto: void:Picture,int kernel_width,int kernel_height,array kernel_values,float filter_weight,int pass_count Desc: Apply a convolution filter to the picture using a user specified kernel of values.

The weight and pass parameters will be 1 in most use case, kernel values are integer in the nominal range [0;255]. Example: function BlurPicture(picture, blur_strength = 1, blur_pass_count = 1) { local kernel = // 7x7 kernel [ 0, 1, 2, 4, 2, 1, 0, 1, 2, 4, 6, 4, 2, 1, 2, 3, 5, 8, 5, 3, 2, 2, 4, 8, 8, 8, 4, 2, 2, 3, 5, 8, 5, 3, 2, 1, 2, 4, 6, 4, 2, 1, 0, 1, 2, 4, 2, 1, 0 ] PictureApplyConvolution(picture, 7, 7, kernel, blur_strength, blur_pass_count) } #*/ sq_register(vm, PictureApplyConvolution, "PictureApplyConvolution", _SC(".xiiani")); /*# Func: PictureLine Proto: bool:Texture,float start_x,float start_y,float end_x,float end_y,Vector rgba Desc: Draw a line, color is specified as an RGBA vector. #*/ sq_register(vm, PictureLine, "PictureLine", _SC(".xnnnnx")); /*# Func: PictureWriteFont Proto: void:Picture,rect,string text,Font font,TextState Desc: Render formatted text to a picture.
TextState is table containing the following keys:
#*/ sq_register(vm, PictureWriteText, "PictureWriteFont", _SC(".xxsxt")); sq_register(vm, PictureWriteText, "PictureWriteText", _SC(".xxsxt")); /*# Func: PictureSetPixel Proto: void:Picture,float x,float y,Vector rgba Desc: Set picture pixel at coordinate {x, y} in picture space from an RGBA vector. #*/ sq_register(vm, PictureSetPixel, "PictureSetPixel", _SC(".xnnx")); /*# Func: PictureGetPixel Proto: Vector:Picture,float x,float y Desc: Return the picture pixel at coordinate {x, y} in picture space as an RGBA vector. #*/ sq_register(vm, PictureGetPixel, "PictureGetPixel", _SC(".xnn")); /*# Section: PictureManipulation Desc: Manipulation #*/ /*# Func: PictureResize Proto: void:Picture,float w,float h Desc: Resize picture. #*/ sq_register(vm, PictureResize, "PictureResize", _SC(".xii")); /*# Func: PictureFlip Proto: void:Picture,bool horizontal, bool vertical Desc: Flip picture on one or both axis. #*/ sq_register(vm, PictureFlip, "PictureFlip", _SC(".xbb")); /*# Section: PictureBlitting Desc: Blitting #*/ /*# Func: PictureBlit Proto: void:Picture source,Picture destination,BlendMode mode Desc: Blit a picture to another picture with a selectable blend mode. #*/ sq_register(vm, PictureBlit, "PictureBlit", _SC(".xxi")); /*# Func: PictureBlitRect Proto: void:Picture source,Picture destination,Rect source,Rect destination,BlendMode mode Desc: Blit a picture to another picture, both clipping zones and the blend mode can be specified. #*/ sq_register(vm, PictureBlitRect, "PictureBlitRect", _SC(".xxxxi")); /*# Func: PictureBlitRectMasked Proto: void:Picture source,Picture destination,Picture mask,Rect source,Rect destination Desc: Blit a picture to another picture using a third picture alpha channel as an opacity mask. #*/ sq_register(vm, PictureBlitRectMasked, "PictureBlitRectMasked", _SC(".xxxxx")); sq_pushroottable(vm); /*# Enum: BlendMode Values: BlendReplace,BlendAdd,BlendCompose,BlendComposeFast,BlendMultiply,BlendMultiply2x,BlendAlphaAdd,BlendAlphaMultiply,BlendAlphaMultiply2x,RgbToAlpha #*/ sq_pushstring(vm, "BlendReplace", -1); sq_pushinteger(vm, Picture::BlendReplace); sq_newslot(vm, -3, true); sq_pushstring(vm, "BlendAdd", -1); sq_pushinteger(vm, Picture::BlendAdd); sq_newslot(vm, -3, true); sq_pushstring(vm, "BlendCompose", -1); sq_pushinteger(vm, Picture::BlendCompose); sq_newslot(vm, -3, true); sq_pushstring(vm, "BlendComposeFast", -1); sq_pushinteger(vm, Picture::BlendComposeFast); sq_newslot(vm, -3, true); sq_pushstring(vm, "BlendMultiply", -1); sq_pushinteger(vm, Picture::BlendMultiply); sq_newslot(vm, -3, true); sq_pushstring(vm, "BlendMultiply2x", -1); sq_pushinteger(vm, Picture::BlendMultiply2x); sq_newslot(vm, -3, true); sq_pushstring(vm, "BlendAlphaAdd", -1); sq_pushinteger(vm, Picture::BlendAlphaAdd); sq_newslot(vm, -3, true); sq_pushstring(vm, "BlendAlphaMultiply", -1); sq_pushinteger(vm, Picture::BlendAlphaMultiply); sq_newslot(vm, -3, true); sq_pushstring(vm, "BlendAlphaMultiply2x", -1); sq_pushinteger(vm, Picture::BlendAlphaMultiply2x); sq_newslot(vm, -3, true); sq_pushstring(vm, "RgbToAlpha", -1); sq_pushinteger(vm, Picture::RgbToAlpha); sq_newslot(vm, -3, true); sq_pop(vm, 1); }