view window/picture.h @ 52:15a18fbe6f21

* Known bugs added to the README * Code cleaning (0 -> NULL when needed, indentation, spaces, ...)
author thib
date Sat, 18 Apr 2009 18:35:39 +0000
parents 5ae5533b3a9a
children e16e13d8cd68
line wrap: on
line source

/*
 * Copyright (c) 2004-2006  Kazunori "jagarl" Ueno
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __PICTURE__
#define __PICTURE__

#include <vector>
#include <list>
#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

class PicBase;
class PicContainer;
class PicRoot;

class Surface;

namespace Event {
	class Video;
}

/* PicBase の内容をイベントと連動させるためのインターフェース */
class PicAnm {
	public:
		typedef std::vector<PicBase*>::iterator iterator;
		std::vector<PicBase*> pic;
		PicAnm(PicBase* pic);
		PicAnm(std::vector<PicBase*> pic);
		virtual ~PicAnm();
};

class PicBase {
	private:
		friend class PicContainer;
		friend class PicWidget;

		typedef std::list<PicBase*> List;
		typedef std::list<PicBase*>::iterator iterator;

		PicContainer* parent;
		class PicWidget* widget;
		Rect rel_pos; // relative position to the parent
		Rect rel_solid_area; // solid area(not alpha-blended) to the parent
		Rect clip_area; // clip area on the parent
		bool is_hidden;
		bool is_hidden_now;
		bool is_cached;
	public:
		enum { /*MOBILE=1,*/ CACHE_BACK=2, /* CACHE_SELF=4,*/ NO_PICTURE=8, SOLID = 16, SURFACE_FREE = 32, FIT_SURFACE = 64, BLIT_SATURATE = 128, BLIT_MULTIPLY = 256, ALPHA_FREE=512};
	private:
		int attribute;

		PicRoot* root;
		iterator z_pos;
		int surface_x, surface_y, surface_w, surface_h;
		Surface* surface_back;
		Surface* surface_own;
		const unsigned char* surface_alpha;
		Rect surface_alpha_rect;
		int distance_root;

		void Blit(const Rect& rpos);
		void Blit(void) {
			is_cached = true;
			Blit(Rect(0, 0, rel_pos.width(), rel_pos.height()));
		}
		/*
		** rpos : relative position to the widget
		** ppos : relative position to the parent
		**	ppos = parent_pos(rpos)
		**	rpos = child_pos(ppos, parent->this_widget)
		** cpos : relative position to a child widget
		**	cpos = child_pos(rpos, a_child_widget)
		** apos : absolute position in the screen
		**	apos = QueryAbsPos(rpos);
		**	or
		**	Rect ppos = rel_pos;
		**	apos = parent->QueryAbsPos(ppos);
		**		the latter form is used for 'rel_pos',
		**		because rel_pos is defined as the relative position to the parent
		*/
		Rect QueryAbsPos(Rect& ppos); // この picture 内の rel_pos を表示するのに実際に必要な絶対座標を得る

		static Rect child_pos(Rect rpos, PicBase* child) { /* return 'cpos' */
			rpos.intersect(child->rel_pos);
			rpos.rmove( -(child->rel_pos.lx), -(child->rel_pos.ty));
			return rpos;
		}
		Rect parent_pos(Rect rpos) { /* return 'ppos' */
			rpos.rmove(rel_pos.lx, rel_pos.ty);
			rpos.intersect(rel_pos);
			return rpos;
		}
		void SetEventWidget(class PicWidget* widget);
	public:
		PicBase(const Rect& rel_pos, PicContainer* parent, int attr);
		virtual ~PicBase();
		void InitRoot(PicRoot* r) { root = r;} // only called from PicRoot::PicRoot

		void ReBlit(const Rect& rpos);
		void ReBlit(void) { ReBlit(Rect(0, 0, rel_pos.width(), rel_pos.height()));}
		void ExecReBlit(const Rect& rpos);
		void SimpleBlit(Surface* screen);

		virtual void RMove(int add_x, int add_y);
		void Move(int new_rx, int new_ry);
		#define ZMOVE_TOP ((PicBase*)0xffff00ff) /* 最前面へ */
		#define ZMOVE_BOTTOM ((PicBase*)0xffff0fff) /* 最背面へ */
		void ZMove(PicBase* back); // back の前に移動(back と自分は同じ親を持つこと)

		void SetSurface(Surface* new_surface, int x, int y, int attribute = 0);
		void SetSurface(const char* new_surface, int x, int y);
		void SetSurfacePos(int x, int y);
		int SurfacePosX(void);
		int SurfacePosY(void);
		void SetSurfaceRect(const Rect& r);
		void SetSurfaceAlpha(const unsigned char* alpha, const Rect& rect);
		void SetSurfaceAlphaFile(const char* file);
		void SetSurfaceColorKey(int r, int g, int b);
		void SetSurfaceAttribute(int attribute);
		void SetSurfaceFreeFlag(bool flag=true);
		void SetClipArea(const Rect& r);

		void hide(void);
		void show_all(void);
		void show(void);

		int PosX(void) const { return rel_pos.lx;}
		int PosY(void) const { return rel_pos.ty;}
		int Width(void) const { return rel_pos.width();}
		int Height(void) const { return rel_pos.height();}
		int DistanceRoot(void) const { return distance_root; }
		bool IsHidden(void) { return is_hidden_now;}
		bool IsParent(PicBase* pic);

		std::vector<PicAnm*> anm;
		void ClearAnm(void);
};

class PicContainer : public PicBase {
	private:
		friend class PicBase;

		void BlitBack(iterator z, Rect rpos); // z より後ろの領域を描画
		void BlitFront(iterator z, Rect rpos); // z を含め、zより前の領域を描画
		void BlitChildren(Rect rpos);
		void BlitSelf(Rect rpos);
		void BlitSelf(void) {
			is_cached = true;
			BlitSelf(Rect(0, 0, rel_pos.width(), rel_pos.height()));
		}
	public:
		List children;
	private:

		void set_showflag(void);
		void set_nowhiddenflag(bool is_hide);
	public:
		PicContainer(const Rect& rel_pos, PicContainer* parent, int attr);
		~PicContainer();
		PicBase* create_leaf(const Rect& rel_pos, int attr);
		PicContainer* create_node(const Rect& rel_pos, int attr);
		PicRoot& Root(void) { return *root;}
		void RMove(int add_x, int add_y);
};

typedef enum { NO_MASK, ALPHA_MASK, COLOR_MASK} MaskType;
struct PicRoot {
	public:
		class PicContainer* root;
	private:
		class FileToSurface* ftosurface;
		struct UpdateItem {
			PicBase* pic;
			Rect rpos;
			Rect apos;
			static bool less(const UpdateItem&, const UpdateItem&);
			UpdateItem(PicBase* p, const Rect& _rpos, const Rect& _apos) : pic(p), rpos(_rpos), apos(_apos) {}
		};
		std::vector<UpdateItem> update_rects;

		friend class FileToSurface;
		void DeleteSurfaceImpl(Surface* s) const;
	public:
		void Update(PicBase* pic, const Rect& rpos, const Rect& apos);
		void DeleteUpdatePic(PicBase* pic);
		void ExecUpdate(void);
		void SetWindowCaption(const char* caption);

		// Surface 操作
		Surface* NewSurfaceFromRGBAData(int w, int h, char* data, MaskType with_mask) const; // data は malloc されたものであること(SDLの内部仕様)
		Surface* NewSurface(int w, int h, MaskType with_mask) const;
		Surface* NewSurface(const char* filename, MaskType with_mask = ALPHA_MASK);
		Surface* RotZoomSurface(Surface* from, double zoom, double rotate_angle);
		void DeleteSurface(Surface* s);
		void BlitSurface(Surface* src, const Rect& src_rpos, const unsigned char* alpha, const Rect& alpha_r,  Surface* dest, const Rect& dest_rpos, int attribute) const;
		void BlitSurface(Surface* src, const Rect& src_rpos, Surface* dest, const Rect& dest_rpos) const {
			BlitSurface(src, src_rpos, 0, Rect(0,0), dest, dest_rpos, 0);
		}
		static bool with_mask(Surface* src);

		Surface* surface;
		Surface* hw_surface;
		int width, height;
		PicRoot(void);
		~PicRoot();
		PicBase* create_leaf(const Rect& apos, int attr) {
			return root->create_leaf(apos, attr);
		}
		PicContainer* create_node(const Rect& apos, int attr) {
			return root->create_node(apos, attr);
		}
};

class PicWidget {
	private:
		PicBase* pic; /* 本来継承するべきだが、遅延初期化したいので instance */
	public:
		PicWidget(void);
		virtual ~PicWidget();
		void SetPic(PicBase* new_pic);
		PicBase* Pic(void);
		PicContainer* PicNode(void);
		virtual void activate(void);
		virtual void deactivate(void);
		virtual void SetRegion(const Rect& apos);
		void show(void);
		void hide(void);
		void show_all(void);
};

#endif /* PICTURE */