?? region_dim.h
字號:
/* * This file is part of Ambulant Player, www.ambulantplayer.org. * * Copyright (C) 2003-2007 Stichting CWI, * Kruislaan 413, 1098 SJ Amsterdam, The Netherlands. * * Ambulant Player is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * Ambulant Player is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Ambulant Player; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *//* * @$Id: region_dim.h,v 1.23 2007/02/12 14:14:09 jackjansen Exp $ */#ifndef AMBULANT_COMMON_REGION_DIM_H#define AMBULANT_COMMON_REGION_DIM_H#include "ambulant/config/config.h"#include "ambulant/lib/gtypes.h"// std::runtime_error#include <stdexcept>// floor#include <math.h>namespace ambulant {namespace common {using namespace lib;/// A representation for a region dimension.////// The respresentation implemented is capable of/// representing auto, absolute or relative coordinates.////// Objects of this class may be used to permanently hold/// the dimensions of a region (as they are specified in the /// original document or by the animated one)./// Conversions to absolute coordinates should be done/// only dynamically, and as late as possible./// An entity having access to the whole layout tree/// (animated or not) should be responsible for all /// on the fly conversions.////// For simplicity we assume that all absolute coordinates/// have been converted to uniform units.class region_dim { /// A type holding either an int (for absolute values) or double (for relative values). union dim_value_holder_t { int int_val; double dbl_val; }; public: ////////////////////// // region_dim constructors /// Default constructor, // constructs an auto region_dim. region_dim() : m_type(rdt_auto) { m_holder.dbl_val = 0;} /// Constructs an absolute dim (assumed in pixels). region_dim(int value) : m_type(rdt_absolute) { m_holder.int_val = value;} /// Constructs a relative dim (proportion or percent). region_dim(double value) : m_type(rdt_relative) { m_holder.dbl_val = value;} // Constructs a region_dim from another region_dim. region_dim(const region_dim& other) : m_type(other.m_type) { if(other.absolute()) m_holder.int_val = other.get_as_int(); else if(other.relative()) m_holder.dbl_val = other.get_as_dbl(); } /// constructs a region_dim from the provided string. /// Does very little error checking. region_dim(const std::string& s) : m_type(rdt_auto) { m_holder.dbl_val = 0; if(s.empty()) return; char *endptr; int ivalue = strtol(s.c_str(), &endptr, 10); if(*endptr == '\0' || strcmp(endptr, "px") == 0) { m_holder.int_val = ivalue; m_type = rdt_absolute; } else if (*endptr == '%') { m_holder.dbl_val = ivalue / 100.0; m_type = rdt_relative; } } ////////////////////// // region_dim destructor ~region_dim(){} ////////////////////// // region_dim assignments (construct from existing) /// Sets this to other. const region_dim& operator=(const region_dim& other) { if(&other != this) { m_type = other.m_type; m_holder = other.m_holder; } return *this; } /// Sets this to the absolute value provided. const region_dim& operator=(int value) { m_type = rdt_absolute; m_holder.int_val = value; return *this; } /// Sets this to the relative value provided. const region_dim& operator=(double value) { m_type = rdt_relative; m_holder.dbl_val = value; return *this; } ////////////////////// // type queries /// Return true if this region_dim is relative. bool relative() const { return m_type == rdt_relative;} /// Return true if this region_dim is absolute. bool absolute() const { return m_type == rdt_absolute;} /// Return true if this region_dim is not auto. bool defined() const { return m_type != rdt_auto;} /// Return true if this region_dim is auto. bool isauto() const { return m_type == rdt_auto;} /// Get value as absolute integer (or abort). int get_as_int() const { if(absolute()) return m_holder.int_val; #ifndef AMBULANT_PLATFORM_WIN32_WCE_3 throw std::runtime_error("Illegal call. Region dim is not absolute");#else abort();#endif return 0; } /// Get value as relative double (or abort). double get_as_dbl() const { if(relative()) return m_holder.dbl_val;#ifndef AMBULANT_PLATFORM_WIN32_WCE_3 throw std::runtime_error("Illegal call. Region dim is not relative");#else abort();#endif return 0; } /// Get value as absolute int. /// Relative values are interpreted with respect to ref, /// auto values will abort. int get(int ref) const { switch(m_type) { case rdt_absolute: return get_as_int(); case rdt_relative: return int(floor(ref*get_as_dbl() + 0.5)); case rdt_auto: break; }#ifndef AMBULANT_PLATFORM_WIN32_WCE_3 throw std::runtime_error("Illegal call. Region dim is undefined");#else abort(); return 0;#endif } /// Return true if two region_dim objects are identical. bool operator== (const region_dim& other) const { if (m_type != other.m_type) return false; if (m_type == rdt_absolute) return m_holder.int_val == other.m_holder.int_val; if (m_type == rdt_relative) return m_holder.dbl_val == other.m_holder.dbl_val; return true; } bool operator!= (const region_dim& other) const { return !(*this == other); } region_dim& operator+=(const region_dim& rhs) { assert(m_type == rhs.m_type); if(absolute()) m_holder.int_val += rhs.get_as_int(); else if(relative()) m_holder.dbl_val += rhs.get_as_dbl(); return *this; } region_dim& operator-=(const region_dim& rhs) { assert(m_type == rhs.m_type); if(absolute()) m_holder.int_val -= rhs.get_as_int(); else if(relative()) m_holder.dbl_val -= rhs.get_as_dbl(); return *this; } region_dim& operator*=(int n) { if(absolute()) m_holder.int_val *= n; else if(relative()) m_holder.dbl_val *= n; return *this; } region_dim& operator/=(int n) { if(absolute()) m_holder.int_val /= n; else if(relative()) m_holder.dbl_val /= n; return *this; } region_dim operator+(const region_dim& rhs) const { region_dim t(*this); t+=rhs; return t;} region_dim operator-(const region_dim& rhs) const { region_dim t(*this); t-=rhs; return t;} region_dim operator*(int n) const { region_dim t(*this); t*=n; return t;} region_dim operator/(int n) const { region_dim t(*this); t/=n; return t;} // define comparisons bool operator<(const region_dim& rhs) const { if(isauto()) return true; return absolute()?(m_holder.dbl_val<rhs.m_holder.dbl_val): m_holder.int_val<rhs.m_holder.int_val;} bool operator<=(const region_dim& rhs) const { if(isauto()) return true; return absolute()?m_holder.dbl_val<= rhs.m_holder.dbl_val: m_holder.int_val<=rhs.m_holder.int_val;} bool operator>(const region_dim& rhs) const { if(isauto()) return true; return absolute()?(m_holder.dbl_val>rhs.m_holder.dbl_val): m_holder.int_val>rhs.m_holder.int_val;} bool operator>=(const region_dim& rhs) const { if(isauto()) return true; return absolute()?m_holder.dbl_val>=rhs.m_holder.dbl_val: m_holder.int_val>=rhs.m_holder.int_val;} private: // region dimension types enum region_dim_type {rdt_auto, rdt_relative, rdt_absolute}; // region dimension data region_dim_type m_type; dim_value_holder_t m_holder;};/// A structure holding all layout attributes of a SMIL region.struct region_dim_spec { /// The 6 possible layout attributes. region_dim left, width, right, top, height, bottom; /// Default constructor, sets all values to auto. region_dim_spec() {} /// Constructor using SMIL anchor coords string. /// For non-rectangular coords values this will set the region_dim_spec /// to the bounding box for the shape. region_dim_spec(const std::string& coords, const char *shape = 0); bool operator== (region_dim_spec& other) const { return left==other.left && width==other.width && right==other.right && top == other.top && height==other.height && bottom==other.bottom; } bool operator!= (region_dim_spec& other) const { return !(*this == other); } /// Convert all relative parameters to absolute. void convert(const lib::rect& rc);};// Sets the region dimensions from the bounding box specified by the coords attributeinline region_dim_spec::region_dim_spec(const std::string& coords, const char *shape) { if(coords.empty()) return; std::list<std::string> list; lib::split_trim_list(coords, list, ','); std::list<std::string>::iterator it = list.begin(); if((!shape || (shape && strcmp(shape, "rect")==0)) && list.size() == 4) { left = region_dim(*it++); top = region_dim(*it++); width = region_dim(*it++) - left; height = region_dim(*it++) - top; } else if((shape && strcmp(shape, "circle")==0) && list.size() == 3) { region_dim x(*it++); region_dim y(*it++); region_dim r(*it++); left = x-r; top = y-r; width = r+r; height = width; } else if((shape && strcmp(shape, "poly")==0) && list.size() >= 6 && (list.size() % 2) == 0) { region_dim l, t, r, b; while(it!=list.end()) { region_dim x(*it++); l = std::min<region_dim>(l, x); r = std::max<region_dim>(r, x); region_dim y(*it++); t = std::min<region_dim>(t, y); b = std::max<region_dim>(b, y); } left = l; top = t; width = r-l; height = b-t; } }// Converts those coordinates that are relative to absolute inline void region_dim_spec::convert(const lib::rect& rc) { int w = rc.width(), h = rc.height(); if(!left.isauto()) left = left.get(w); if(!right.isauto()) right = right.get(w); if(!width.isauto()) width = width.get(w); if(!top.isauto()) top = top.get(h); if(!bottom.isauto()) bottom = bottom.get(h); if(!height.isauto()) height = height.get(h);}/// A structure holding attributes of a SMIL regPoint or regAlign./// A region node may hold along its other attributes this data structure.struct regpoint_spec { /// The two coordinates. region_dim left, top; /// Default constructor initializes everything to auto. regpoint_spec() {} /// Specific constructor giving percentage values. regpoint_spec(double hor, double vert) : left(hor), top(vert) {} bool operator== (regpoint_spec& other) const { return left==other.left && top == other.top; } bool operator!= (regpoint_spec& other) const { return !(*this == other); }};} // namespace common } // namespace ambulantinline std::string repr(const ambulant::common::region_dim& rd) { char sz[16] = "<auto>"; if(rd.relative()) sprintf(sz, "%d%c", int(floor(0.5+rd.get_as_dbl() * 100.0)), '%'); else if(rd.absolute()) sprintf(sz, "%d", rd.get_as_int()); return sz;}///////////////////////////////#ifndef AMBULANT_NO_IOSTREAMS_HEADERS// std::ostream for debug output#ifndef AMBULANT_NO_OSTREAM#include <ostream>#else /*AMBULANT_NO_OSTREAM*/#include <ostream.h>#endif/*AMBULANT_NO_OSTREAM*/#endif // AMBULANT_NO_IOSTREAMS_HEADERS///////////////////////////////#ifndef AMBULANT_NO_OSTREAM// debug region_dim print outinline std::ostream& operator<<(std::ostream& os, const ambulant::common::region_dim& rd) { if(rd.relative()) return os << rd.get_as_dbl() * 100.0 << '%' ; else if(rd.absolute()) return os << rd.get_as_int(); return os << "<auto>";}// debug region_dim_spec printoutinline std::ostream& operator<<(std::ostream& os, const ambulant::common::region_dim_spec& rds) { os << '(' << rds.left << ", " << rds.width << ", " << rds.right; os << ", " << rds.top << ", " << rds.height << ", " << rds.bottom; return os << ')';}#endif#endif // AMBULANT_COMMON_REGION_DIM_H
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -