QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

楼主: asmcos

窗口裁减

[复制链接]
 楼主| 发表于 2006-6-17 18:45:28 | 显示全部楼层
我整理一下你说的办法。

1. A为底层窗口
2. 有N个窗口和A相交。B,C,D,。。。。。

你的意思计算方法如下:
先算A和B相交,计算可能出现的暴露区域,A0(完全遮盖,不需要存储暴露区域),A1,A2,A3,A4。

在分别计算A1,和C相交暴露的区域。在计算A2,A3,A4....
结果有16种可能 AA1,AA2,。。。AA16

在将AA1---AA16于D计算。。。。。
直到N,

是这个意思吗?
回复

使用道具 举报

 楼主| 发表于 2006-6-17 18:49:12 | 显示全部楼层
这确实也是一种方法。

计算量不小。

我试着写个程序看看,呵呵。

再此前,我也有过这个想法,觉得太复杂,就没有仔细推想。
回复

使用道具 举报

发表于 2006-6-17 18:52:57 | 显示全部楼层
首先,窗口的draw这个动作本省,不需要考虑自身的有效区域的。
考虑者的应该是下层的绘图lib
回复

使用道具 举报

发表于 2006-6-17 18:57:06 | 显示全部楼层
窗体管理本来就有些复杂。
这点计算量小菜一叠
回复

使用道具 举报

发表于 2006-6-17 19:00:22 | 显示全部楼层
当然很多可以优化,比如我们可以只通过可视区域去剪切。
回复

使用道具 举报

 楼主| 发表于 2006-6-17 19:28:25 | 显示全部楼层
先写一个,再考虑优化了。
回复

使用道具 举报

发表于 2006-6-17 22:52:34 | 显示全部楼层
[quote:ac92f7cb82="asmcos"]ETK++代码何时开放?或者你能讲解一下Etk上述几种情况的实现.?[/quote]

等到ETK++基本能相当于glib+gtk+gprint+gnet+glade的时候代码会开放,
最近因为本职工作较忙,所以进展不大。

你提到的问题解决方法用ETK++写类似以下:
[code:1]
// 编译: g++ `pkg-config --cflags --libs etkxx` test.cpp -o a.out
// a.out 执行结果:
//         ERect(50, 50, 200, 200)  /* 这是它的最大范围 */
//         ERect(50, 100, 200, 150) /* 第 1 个矩形 */
//         ERect(150, 150, 200, 200) /* 第 2 个矩形 */
//         ERect(50, 50, 100, 100) /* 第 3 个矩形 */


#include <etk/interface/Region.h>

int main(int argc, char **argv)
{
        // 这里因为原BeOS API的特殊模式(适用于Print)
        // 所以所有坐标均为浮点数
        ERect rectA(50, 50, 200, 200);
        ERect rectB(100, 20, 250, 100);
        ERect rectC(10, 150, 150, 300);
        ERegion regionLastA(rectA);
        regionLastA.Exclude(rectB);
        regionLastA.Exclude(rectC);
        regionLastA.PrintToStream();
        return 0;
}
[/code:1]

下面是etkxx-0.1.11/etk/interface/Region.cpp的代码:
[code:1]
/* --------------------------------------------------------------------------
*
* ETK++ --- The Easy Toolkit for C++ programing
* Copyright (C) 2004-2006, Anthony Lee, All Rights Reserved
*
* $COPYING
*
* File: Region.cpp
* Description: ERegion --- Combination of rectangles to describe region
*
* --------------------------------------------------------------------------*/

/* --------------------------------------------------------------------------
<document lang="zh_CN.UTF-8">
<documentinfo>
        <title>区域范围描述</title>
        <legalnotice>版权所有 (C) 2004-2006, Anthony Lee</legalnotice>
        <authorgroup>
                <author>
                        <honorific>作者</honorific>
                        <othername>Anthony Lee</othername>
                        <address>
                                <city>广州<city>
                                <country>中国<country>
                                <email>[email protected]</email>
                        </address>
                </author>
        </authorgroup>
        <revhistory>
                <revision>
                        <revnumber>0.0.1</revnumber>
                        <date>Sat, 15 Apr 2006 01:09:23 +0800</date>
                        <revremark>尝试用DocBook语法内嵌在源码中来写开发手册</revremark>
                </revision>
                <revision>
                        <revnumber>0.0.2</revnumber>
                        <date>Sat, 17 Jun 2006 22:43:59 +0800</date>
                        <revremark>基本完成ERegion的中文文档</revremark>
                </revision>
        </revhistory>
</documentinfo>
<section linkend="EREGION_DESCRIPTION" />
<section linkend="EREGION_FUNCTIONS" />
</document>
-----------------------------------------------------------------------------*/

/* --------------------------------------------------------------------------
<document lang="zh_CN.UTF-8">
<section id="EREGION_DESCRIPTION">
        <title>ERegion类描述</title>
        <para>声明所在:<emphasis><etk/interface/Region.h></emphasis></para>
        <para>链 接 库:<emphasis>libetkxx</emphasis></para>
        <para>派生关系:<emphasis>ERegion</emphasis></para>
        <para>ERegion是一个由多个矩形组合的区域范围描述类,主要用于描述不规则区域。</para>
</section>

<section id="EREGION_FUNCTIONS" lang="zh_CN.UTF-8">
        <title>ERegion类成员函数</title>
        <section linkend="EREGION_FUNCTION_CONSTRUCT" />
        <section linkend="EREGION_FUNCTION_OPERATOR" />
        <section linkend="EREGION_FUNCTION_FRAME" />
        <section linkend="EREGION_FUNCTION_COUNT_RECTS" />
        <section linkend="EREGION_FUNCTION_RECT_AT" />
        <section linkend="EREGION_FUNCTION_MODIFICATION" />
        <section linkend="EREGION_FUNCTION_QUERY" />
</section>
</document>
-----------------------------------------------------------------------------*/

#include "Region.h"

/* --------------------------------------------------------------------------
<document lang="zh_CN.UTF-8">
<section id="EREGION_FUNCTION_CONSTRUCT">
        <title>构造函数</title>
        <programlisting>
ERegion::ERegion()
ERegion::ERegion(const ERegion &<emphasis>region</emphasis>)
ERegion::ERegion(const ERect &<emphasis>rect</emphasis>)
virtual ERegion::~ERegion()
        </programlisting>
        <itemizedlist>
                <listitem><para><emphasis>region</emphasis>是已创建的区域范围描述。
                </para></listitem>
                <listitem><para><emphasis>rect</emphasis>是初始的一个矩形区域范围。
                </para></listitem>
        </itemizedlist>
</section>
</document>
-----------------------------------------------------------------------------*/
ERegion::ERegion()
{
}


ERegion::ERegion(const ERegion &region)
{
        if(region.fRects.CountItems() > 0) *this = region;
}


ERegion::ERegion(const ERect &rect)
{
        Set(rect);
}


ERegion::~ERegion()
{
        MakeEmpty();
}


/* --------------------------------------------------------------------------
<document lang="zh_CN.UTF-8">
<section id="EREGION_FUNCTION_OPERATOR">
        <title>区域范围操作符</title>
        <programlisting>
ERegion& ERegion::operator=(const ERegion &<emphasis>region</emphasis>)

ERegion ERegion::operator&(ERect <emphasis>rect</emphasis>) const
ERegion ERegion::operator|(ERect <emphasis>rect</emphasis>) const

ERegion& ERegion::operator&=(ERect <emphasis>rect</emphasis>)
ERegion& ERegion::operator|=(ERect <emphasis>rect</emphasis>)

ERegion ERegion::operator&(const ERegion &<emphasis>region</emphasis>) const
ERegion ERegion::operator|(const ERegion &<emphasis>region</emphasis>) const

ERegion& ERegion::operator&=(const ERegion &<emphasis>region</emphasis>)
ERegion& ERegion::operator|=(const ERegion &<emphasis>region</emphasis>)
        </programlisting>
        <itemizedlist>
                <listitem><para><emphasis>region</emphasis>与其操作的区域范围描述。
                        <footnote><para>如果该区域范围描述为无效区域时,进行赋值(operator=)
                                        或位与(operator&=)操作时会导致当前区域范围描述无效。</para></footnote>
                </para></listitem>
                <listitem><para><emphasis>rect</emphasis>与其操作的矩形区域。
                        <footnote><para>如果该矩形为无效矩形时,进行赋值(operator=)
                                        或位与(operator&=)操作时会导致当前区域范围描述无效。</para></footnote>
                </para></listitem>
        </itemizedlist>
        <para>ERegion::operator=()用于赋值给当前区域,返回值为赋值后的当前区域本身引用。</para>
        <para>ERegion::operator&()用于求当前区域与指定参数的交集,返回值为相交的区域。</para>
        <para>ERegion::operator&=()用于将当前区域与指定参数进行交集操作,返回值为操作后的当前区域本身引用。</para>
        <para>ERegion::operator|()用于求当前区域与指定参数的并集,返回值为联合的区域。</para>
        <para>ERegion::operator|=()用于将当前区域与指定参数进行并集操作,返回值为操作后的当前区域本身引用。</para>
</section>
</document>
-----------------------------------------------------------------------------*/
ERegion&
ERegion::operator=(const ERegion &from)
{
        MakeEmpty();

        if(from.fRects.CountItems() > 0)
        {
                for(eint32 i = 0; i < from.fRects.CountItems(); i++)
                {
                        ERect *r = (ERect*)from.fRects.ItemAt(i);
                        ERect *nr = ((!r || r->IsValid() == false) ? NULL : new ERect(*r));
                        if(!nr || fRects.AddItem(nr) == false)
                        {
                                if(nr) delete nr;
                                MakeEmpty();
                                break;
                        }
                        else
                        {
                                fFrame = (fFrame.IsValid() ? (fFrame | *r) : *r);
                        }
                }
        }

        return *this;
}


/* --------------------------------------------------------------------------
<document lang="zh_CN.UTF-8">
<section id="EREGION_FUNCTION_FRAME">
        <title>区域描述的最大矩形范围</title>
        <programlisting>
ERect ERegion::Frame() const
        </programlisting>
        <para>返回值为该区域描述的最大矩形范围,当区域无效时返回值亦无效。</para>
</section>
</document>
-----------------------------------------------------------------------------*/
ERect
ERegion::Frame() const
{
        return fFrame;
}


/* --------------------------------------------------------------------------
<document lang="zh_CN.UTF-8">
<section id="EREGION_FUNCTION_RECT_AT">
        <title>区域描述的组成矩形</title>
        <programlisting>
ERect ERegion::RectAt(eint32 <emphasis>index</emphasis>) const
        </programlisting>
        <itemizedlist>
                <listitem><para><emphasis>index</emphasis>是组成矩形的位置索引。
                <footnote><para>其值应界于0和ERegion::CountRects() - 1之间。</para></footnote>
                </para></listitem>
        </itemizedlist>
        <para>返回值为该区域第index+1个组合矩形,当index处于无效范围时返回值亦无效。</para>
</section>
</document>
-----------------------------------------------------------------------------*/
ERect
ERegion::RectAt(eint32 index) const
{
        ERect *r = (ERect*)fRects.ItemAt(index);
        return(r ? *r : ERect());
}


/* --------------------------------------------------------------------------
<document lang="zh_CN.UTF-8">
<section id="EREGION_FUNCTION_COUNT_RECTS">
        <title>区域描述的组成矩形数量</title>
        <programlisting>
eint32 ERegion::CountRects() const
        </programlisting>
        <para>返回值为该区域描述的组合矩形数量。
                <footnote><para>一个区域范围描述由多个矩形成员组成,
                                ERegion::CountRects()主要用于统计
                                组成矩形的数量以便调用ERegion::RectAt()。</para></footnote>
        </para>
</section>
</document>
-----------------------------------------------------------------------------*/
eint32
ERegion::CountRects() const
{
        return fRects.CountItems();
}


/* --------------------------------------------------------------------------
<document lang="zh_CN.UTF-8">
<section id="EREGION_FUNCTION_MODIFICATION">
        <title>区域描述的修改与设定</title>
        <programlisting>
void ERegion::Set(ERect <emphasis>singleBound</emphasis>)
void ERegion::MakeEmpty()

bool ERegion::Include(ERect <emphasis>rect</emphasis>)
bool ERegion::Include(const ERegion *<emphasis>region</emphasis>)

bool ERegion::Exclude(ERect <emphasis>rect</emphasis>)
bool ERegion::Exclude(const ERegion *<emphasis>region</emphasis>)

void ERegion::OffsetBy(float <emphasis>dx</emphasis>, float <emphasis>dy</emphasis>)
void ERegion::OffsetBy(EPoint <emphasis>pt</emphasis>)
ERegion& ERegion::OffsetBySelf(float <emphasis>dx</emphasis>, float <emphasis>dy</emphasis>)
ERegion& ERegion::OffsetBySelf(EPoint <emphasis>pt</emphasis>)
ERegion ERegion::OffsetByCopy(float <emphasis>dx</emphasis>, float <emphasis>dy</emphasis>)
ERegion ERegion::OffsetByCopy(EPoint <emphasis>pt</emphasis>)

void ERegion::Scale(float <emphasis>scaling</emphasis>)
ERegion& ERegion::ScaleSelf(float <emphasis>scaling</emphasis>)
ERegion ERegion::ScaleCopy(float <emphasis>scaling</emphasis>)
        </programlisting>
        <itemizedlist>
                <listitem><para><emphasis>singleBound</emphasis>是一个矩形的区域范围描述。
                        <footnote><para>如果该矩形为无效矩形时会导致当前区域范围描述无效。</para></footnote>
                </para></listitem>
                <listitem><para><emphasis>region</emphasis>是已有的区域范围描述。
                </para></listitem>
                <listitem><para><emphasis>rect</emphasis>是已有的一个矩形区域范围。
                </para></listitem>
                <listitem><para><emphasis>dx</emphasis>是相对的偏移X方向量。
                </para></listitem>
                <listitem><para><emphasis>dy</emphasis>是相对的偏移Y方向量。
                </para></listitem>
                <listitem><para><emphasis>pt</emphasis>是相对的偏移X和Y方向量的点组合。
                        <footnote><para>pt.x和pt.y相对应上述的dx和dy。</para></footnote>
                </para></listitem>
                <listitem><para><emphasis>scaling</emphasis>是缩放的比例。
                        <footnote><para>scaling不能小于0。</para></footnote>
                </para></listitem>
        </itemizedlist>
        <para>ERegion::Set()用于将当前区域描述赋值成一个单独的矩形区域。
                <footnote><para>如果该矩形为无效矩形时会导致当前区域范围描述无效。</para></footnote>
        </para>
        <para>ERegion::MakeEmpty()用于清除当前区域描述的所有组成矩形。</para>
        <para>ERegion::Include()用于将参数指定的区域试图加入到当前区域描述中,成功时返回值为true,否则为false。</para>
        <para>ERegion::Exclude()用于将参数指定的区域试图从当前区域描述中排除,成功时返回值为true,否则为false。</para>
        <para>ERegion::OffsetBy()用于将当前区域描述的所有组成矩形都按指定相对位移进行偏移。</para>
        <para>ERegion::OffsetBySelf()用于将当前区域描述的所有组成矩形都按指定相对位移进行偏移,返回值为偏移后的当前区域本身引用。</para>
        <para>ERegion::OffsetByCopy()用于求当前区域描述的所有组成矩形都按指定相对位移进行偏移的结果,返回值为偏移后的区域描述。</para>
        <para>ERegion::Scale()用于将当前区域描述的所有组成矩形都按指定比例进行放缩。</para>
        <para>ERegion::ScaleSelf()用于将当前区域描述的所有组成矩形都按指定比例进行放缩,返回值为放缩后的当前区域本身引用。</para>
        <para>ERegion::ScaleCopy()用于求当前区域描述的所有组成矩形都按指定比例进行放缩的结果,返回值为放缩后的区域描述。</para>
</section>
</document>
-----------------------------------------------------------------------------*/
void
ERegion::Set(ERect rect)
{
        MakeEmpty();

        if(rect.IsValid())
        {
                ERect *r = new ERect(rect);

                if(r)
                {
                        if(fRects.AddItem(r))
                                fFrame = rect;
                        else
                                delete r;
                }
        }
}


void
ERegion::MakeEmpty()
{
        for(eint32 i = 0; i < fRects.CountItems(); i++)
        {
                ERect *r = (ERect*)fRects.ItemAt(i);
                if(r) delete r;
        }

        fRects.MakeEmpty();
        fFrame = ERect();
}


// return value must free by "delete[]"
inline ERect* rect_exclude(ERect s, ERect r, eint8 *nRects)
{
        if(!r.IsValid() || !s.IsValid() || !nRects) return NULL;

        ERect iR = (s & r);
        if(!iR.IsValid() || iR == s)
        {
                *nRects = 0;
                return NULL;
        }

        ERect *rects = new ERect[4];
        if(!rects)
        {
                *nRects = -1;
                return NULL;
        }

        rects[0].Set(min_c(s.left, iR.left), min_c(s.top, iR.top), max_c(s.right, iR.right), max_c(s.top, iR.top)); // top
        rects[1].Set(min_c(s.left, iR.left), min_c(s.bottom, iR.bottom), max_c(s.right, iR.right), max_c(s.bottom, iR.bottom)); // bottom
        rects[2].Set(min_c(s.left, iR.left), max_c(s.top, iR.top), max_c(s.left, iR.left), min_c(s.bottom, iR.bottom)); // left
        rects[3].Set(min_c(s.right, iR.right), max_c(s.top, iR.top), max_c(s.right, iR.right), min_c(s.bottom, iR.bottom)); // right

        eint8 count = 4;
        for(eint8 i = 0; i < count; i++)
        {
                if((rects[i].Width() == 0 && s.Width() > 0) || (rects[i].Height() == 0 && s.Height() > 0) || !rects[i].IsValid())
                {
                        for(eint8 j = i; j < count - 1; j++) rects[j] = rects[j + 1];
                        count--; i--;
                }
        }

        *nRects = count;

        if(count > 0) return rects;

        delete[] rects;
        return NULL;
}


bool
ERegion::Include(ERect rect)
{
        if(rect.IsValid() == false) return false;

        ERect *rects = ▭
        eint32 nRects = 1;

        for(eint32 i = 0; i < fRects.CountItems(); i++)
        {
                ERect *r = (ERect*)fRects.ItemAt(i);

                ERect **rs = ((!r || r->IsValid() == false) ? NULL : new ERect*[nRects]);
                eint8 *nrs = ((!r || r->IsValid() == false) ? NULL : new eint8[nRects]);
                eint32 nNeeded = 0;
                bool haveNew = false;

                if(rs && nrs)
                {
                        for(eint32 j = 0; j < nRects; j++)
                        {
                                if(r->Intersect(rects[j]))
                                {
                                        rs[j] = rect_exclude(rects[j], *r, &(nrs[j]));
                                        if(nrs[j] < 0 || (rs[j] == NULL && nrs[j] > 0) || nNeeded >= E_MAXINT32 - nrs[j])
                                        {
                                                nNeeded = -(j + 1);
                                                break;
                                        }
                                        else
                                        {
                                                haveNew = true;
                                                nNeeded += nrs[j];
                                        }
                                }
                                else
                                {
                                        rs[j] = &(rects[j]);
                                        nrs[j] = 1;
                                        nNeeded++;
                                }
                        }
                }

                if(!rs || !nrs || nNeeded < 0)
                {
                        if(rs && nrs) for(eint32 j = 0; j <= -(nNeeded + 1); j++) if(rs[j] != NULL && rs[j] != &(rects[j])) delete[] rs[j];
                        if(rs) delete[] rs;
                        if(nrs) delete[] nrs;

                        if(rects != &rect) delete[] rects;
                        return false;
                }
                else if(nNeeded == 0 && haveNew)
                {
                        for(eint32 j = 0; j < nRects; j++) if(rs[j] != NULL && rs[j] != &(rects[j])) delete[] rs[j];
                        delete[] rs;
                        delete[] nrs;

                        if(rects != &rect) delete[] rects;
                        return true;
                }

                ERect *newRects = ((nNeeded > 0 && haveNew) ? new ERect[nNeeded] : NULL);
                ERect *tmp = newRects;
                for(eint32 j = 0; j < nRects; j++)
                {
                        if(tmp && nrs[j] > 0)
                        {
                                memcpy(tmp, rs[j], sizeof(ERect) * (size_t)nrs[j]);
                                tmp += nrs[j];
                        }
                        if(rs[j] != NULL && rs[j] != &(rects[j])) delete[] rs[j];
                }

                delete[] rs;
                delete[] nrs;

                if(newRects)
                {
                        if(rects != &rect) delete[] rects;
                        rects = newRects;
                        nRects = nNeeded;
                }
        }

        eint32 oldLength = fRects.CountItems();
        ERect oldFrame = fFrame;

        for(eint32 i = 0; i < nRects; i++)
        {
                ERect *r = new ERect(rects[i]);
                if(!r || r->IsValid() == false || fRects.AddItem(r) == false)
                {
                        if(r) delete r;
                        if(rects != &rect) delete[] rects;

                        if(fRects.CountItems() > oldLength)
                        {
                                for(eint32 i = oldLength; i < fRects.CountItems(); i++)
                                {
                                        r = (ERect*)fRects.ItemAt(i);
                                        if(r) delete r;
                                }
                                fRects.RemoveItems(oldLength, -1);
                        }
                        fFrame = oldFrame;

                        return false;
                }
                fFrame = (fFrame.IsValid() ? (fFrame | *r) : *r);
        }

        if(rects != &rect) delete[] rects;
        return true;
}


bool
ERegion::Include(const ERegion *region)
{
        if(region == NULL || region->CountRects() <= 0) return false;

        eint32 oldLength = fRects.CountItems();
        ERect oldFrame = fFrame;

        for(eint32 i = 0; i < region->CountRects(); i++)
        {
                ERect r = region->RectAt(i);
                if(r.IsValid() == false || Include(r) == false)
                {
                        if(fRects.CountItems() > oldLength)
                        {
                                for(eint32 i = oldLength; i < fRects.CountItems(); i++)
                                {
                                        ERect *ar = (ERect*)fRects.ItemAt(i);
                                        if(ar) delete ar;
                                }
                                fRects.RemoveItems(oldLength, -1);
                        }
                        fFrame = oldFrame;
                        return false;
                }
        }

        return true;
}


bool
ERegion::Exclude(ERect r)
{
        if(Intersect(r) == false) return true;

        eint32 offset = 0;
        ERect rect;
        bool retVal = true;

        ERegion aRegion(*this);
        if(aRegion.CountRects() != CountRects() || aRegion.Frame() != Frame()) return false;

        while(offset < aRegion.fRects.CountItems())
        {
                rect = aRegion.RectAt(offset);
                if(rect.IsValid() == false) {retVal = false; break;}
                if(rect.Intersect(r) == false) {offset++; continue;}

                eint8 nrs = 0;
                ERect *rs = rect_exclude(rect, r, &nrs);
                if(nrs < 0 || (rs == NULL && nrs > 0)) {if(rs) delete[] rs; retVal = false; break;}

                for(eint8 i = 0; i < nrs; i++)
                {
                        ERect *tr = new ERect(rs[i]);
                        if(!tr || tr->IsValid() == false || aRegion.fRects.AddItem(tr, offset) == false)
                        {
                                if(tr) delete tr;
                                retVal = false;
                                break;
                        }
                        offset++;
                }

                if(rs) delete[] rs;
                if(!retVal) break;

                ERect *ar = (ERect*)aRegion.fRects.RemoveItem(offset);
                if(!ar) {retVal = false; break;}
                delete ar;

                if(nrs == 0) break; // here the "rect == r", so we break
        }

        if(retVal)
        {
                MakeEmpty();
                if(fRects.AddList(&(aRegion.fRects))) aRegion.fRects.MakeEmpty();
                for(eint32 i = 0; i < fRects.CountItems(); i++)
                {
                        ERect *r = (ERect*)fRects.ItemAt(i);
                        fFrame = (fFrame.IsValid() ? (fFrame | *r) : *r);
                }
        }

        return retVal;
}


bool
ERegion::Exclude(const ERegion *region)
{
        if(Intersect(region) == false) return true;

        ERegion aRegion(*this);
        if(aRegion.CountRects() != CountRects() || aRegion.Frame() != Frame()) return false;

        bool retVal = true;

        for(eint32 i = 0; i < region->CountRects(); i++)
        {
                ERect r = region->RectAt(i);
                if(aRegion.Exclude(r) == false) {retVal = false; break;}
        }

        if(retVal)
        {
                MakeEmpty();
                if(fRects.AddList(&(aRegion.fRects))) aRegion.fRects.MakeEmpty();
                for(eint32 i = 0; i < fRects.CountItems(); i++)
                {
                        ERect *r = (ERect*)fRects.ItemAt(i);
                        fFrame = (fFrame.IsValid() ? (fFrame | *r) : *r);
                }
        }

        return retVal;
}


void
ERegion::OffsetBy(float dx, float dy)
{
        if(fRects.CountItems() <= 0) return;

        for(eint32 i = 0; i < fRects.CountItems(); i++)
        {
                ERect *r = (ERect*)fRects.ItemAt(i);
                r->OffsetBy(dx, dy);
        }
        fFrame.OffsetBy(dx, dy);
}


void
ERegion::OffsetBy(EPoint pt)
{
        OffsetBy(pt.x, pt.y);
}


ERegion&
ERegion::OffsetBySelf(float dx, float dy)
{
        OffsetBy(dx, dy);
        return *this;
}


ERegion&
ERegion::OffsetBySelf(EPoint pt)
{
        OffsetBy(pt.x, pt.y);
        return *this;
}


ERegion
ERegion::OffsetByCopy(float dx, float dy)
{
        ERegion aRegion(*this);
        aRegion.OffsetBy(dx, dy);
        return aRegion;
}


ERegion
ERegion::OffsetByCopy(EPoint pt)
{
        ERegion aRegion(*this);
        aRegion.OffsetBy(pt.x, pt.y);
        return aRegion;
}


/* --------------------------------------------------------------------------
<document lang="zh_CN.UTF-8">
<section id="EREGION_FUNCTION_QUERY">
        <title>区域描述的查询</title>
        <programlisting>
bool ERegion::Intersect(ERect <emphasis>rect</emphasis>) const;
bool ERegion::Intersect(float <emphasis>left</emphasis>, float <emphasis>top</emphasis>, float <emphasis>right</emphasis>, float <emphasis>bottom</emphasis>) const;
bool ERegion::Intersect(const ERegion *<emphasis>region</emphasis>) const;

bool ERegion::Contains(EPoint <emphasis>pt</emphasis>) const;
bool ERegion::Contains(float <emphasis>x</emphasis>, float <emphasis>y</emphasis>) const;
bool ERegion::Contains(ERect <emphasis>rect</emphasis>) const;
bool ERegion::Contains(float <emphasis>left</emphasis>, float <emphasis>top</emphasis>, float <emphasis>right</emphasis>, float <emphasis>bottom</emphasis>) const;
bool ERegion::Contains(const ERegion *<emphasis>region</emphasis>) const;

void ERegion::PrintToStream() const;
        </programlisting>
        <itemizedlist>
                <listitem><para><emphasis>region</emphasis>是已有的区域范围描述。
                </para></listitem>
                <listitem><para><emphasis>rect</emphasis>是已有的一个矩形区域范围。
                </para></listitem>
                <listitem><para><emphasis>left top right bottom</emphasis>分别是已有的一个矩形区域范围的左、上、右、下坐标值。
                </para></listitem>
                <listitem><para><emphasis>pt</emphasis>是一个点。
                </para></listitem>
                <listitem><para><emphasis>x y</emphasis>分别是一个点的X、Y方向坐标值。
                </para></listitem>
        </itemizedlist>
        <para>ERegion::Intersect()用于查询参数指定的矩形或区域描述与当前区域描述是否相交,有相交时返回true,否则返回false。</para>
        <para>ERegion::Contains()用于查询参数指定的点、矩形或区域描述是否在当前区域描述之内,被其完全包含时返回true,否则返回false。</para>
        <para>ERegion::PrintToStream()用于将当前区域描述的所有组成矩形内容打印到标准输出流中。
                <footnote><para>ERegion::PrintToStream()主要用于调试,无其它特殊效用。</para></footnote>
        </para>
</section>
</document>
-----------------------------------------------------------------------------*/
bool
ERegion::Intersect(ERect rect) const
{
        return Intersect(rect.left, rect.top, rect.right, rect.bottom);
}


bool
ERegion::Intersect(float l, float t, float r, float b) const
{
        if(fFrame.Intersect(l, t, r, b) == false) return false;

        for(eint32 i = 0; i < fRects.CountItems(); i++)
        {
                ERect *rect = (ERect*)fRects.ItemAt(i);
                if(!rect || rect->IsValid() == false) return false;
                if(rect->Intersect(l, t, r, b)) return true;
        }

        return false;
}


bool
ERegion::Intersect(const ERegion *region) const
{
        if(!region || fFrame.Intersect(region->fFrame) == false) return false;

        for(eint32 i = 0; i < fRects.CountItems(); i++)
        {
                ERect *rect = (ERect*)fRects.ItemAt(i);
                if(!rect || rect->IsValid() == false) return false;

                for(eint32 j = 0; j < region->fRects.CountItems(); j++)
                {
                        ERect *ar = (ERect*)region->fRects.ItemAt(j);
                        if(!ar || ar->IsValid() == false) return false;
                        if(ar->Intersect(*rect)) return true;
                }
        }

        return false;
}


bool
ERegion::Contains(EPoint pt) const
{
        return Contains(pt.x, pt.y);
}


bool
ERegion::Contains(float x, float y) const
{
        if(fFrame.Contains(x, y) == false) return false;

        for(eint32 i = 0; i < fRects.CountItems(); i++)
        {
                ERect *r = (ERect*)fRects.ItemAt(i);
                if(!r || r->IsValid() == false) return false;
                if(r->Contains(x, y)) return true;
        }

        return false;
}


bool
ERegion::Contains(ERect rect) const
{
        ERegion aRegion(rect);
        return Contains(&aRegion);
}


bool
ERegion::Contains(float l, float t, float r, float b) const
{
        return Contains(ERect(l, t, r, b));
}


bool
ERegion::Contains(const ERegion *region) const
{
        if(!region || fFrame.Contains(region->fFrame) == false) return false;

        ERegion aRegion(*region);
        if(aRegion.CountRects() != region->CountRects() || aRegion.Frame() != region->Frame()) return false;

        if(aRegion.Exclude(this) == false || aRegion.fRects.CountItems() > 0) return false;

        return true;
}


void
ERegion::PrintToStream() const
{
        fFrame.PrintToStream();
        for(eint32 i = 0; i < fRects.CountItems(); i++)
        {
                ERect *r = (ERect*)fRects.ItemAt(i);
                if(r) r->PrintToStream();
        }
}


ERegion
ERegion::operator&(ERect r) const
{
        ERegion aRegion(*this);
        if(aRegion.CountRects() != CountRects() || aRegion.Frame() != Frame()) aRegion.MakeEmpty();

        aRegion &= r;

        return aRegion;
}


ERegion
ERegion::operator|(ERect r) const
{
        ERegion aRegion(*this);
        if(aRegion.CountRects() != CountRects() || aRegion.Frame() != Frame()) aRegion.MakeEmpty();

        aRegion |= r;

        return aRegion;
}


ERegion&
ERegion::operator&=(ERect r)
{
        if(fFrame.Intersect(r) == false) MakeEmpty();
        else
        {
                eint32 offset = 0;
                while(offset < fRects.CountItems())
                {
                        ERect *rect = (ERect*)fRects.ItemAt(offset);
                        if(!rect || rect->IsValid() == false) {MakeEmpty(); break;}

                        *rect &= r;
                        if(rect->IsValid() == false)
                        {
                                rect = (ERect*)fRects.RemoveItem(offset);
                                if(!rect) {MakeEmpty(); break;}
                                delete rect;
                                continue;
                        }

                        offset++;
                }
        }

        fFrame = ERect();
        for(eint32 i = 0; i < fRects.CountItems(); i++)
        {
                ERect *rect = (ERect*)fRects.ItemAt(i);
                fFrame = (fFrame.IsValid() ? (fFrame | *rect) : *rect);
        }

        return *this;
}


ERegion&
ERegion::operator|=(ERect r)
{
        Include(r);
        return *this;
}


ERegion
ERegion::operator&(const ERegion &region) const
{
        ERegion aRegion(*this);
        if(aRegion.CountRects() != CountRects() || aRegion.Frame() != Frame()) aRegion.MakeEmpty();

        aRegion &= region;

        return aRegion;
}


ERegion
ERegion::operator|(const ERegion &region) const
{
        ERegion aRegion(*this);
        if(aRegion.CountRects() != CountRects() || aRegion.Frame() != Frame()) aRegion.MakeEmpty();

        aRegion |= region;

        return aRegion;
}


ERegion&
ERegion::operator&=(const ERegion &region)
{
        if(fFrame.Intersect(region.fFrame) == false) MakeEmpty();
        else
        {
                operator&=(region.fFrame);
                if(region.CountRects() > 1)
                {
                        ERegion aRegion(region.fFrame);
                        aRegion.Exclude(&region);
                        Exclude(&aRegion);
                }
        }

        return *this;
}


ERegion&
ERegion::operator|=(const ERegion &region)
{
        Include(&region);
        return *this;
}


void
ERegion::Scale(float scaling)
{
        if(fRects.CountItems() <= 0 || scaling < 0 || scaling == 1) return;

        if(scaling > 0)
        {
                for(eint32 i = 0; i < fRects.CountItems(); i++)
                {
                        ERect *r = (ERect*)fRects.ItemAt(i);
                        r->left *= scaling;
                        r->top *= scaling;
                        r->right *= scaling;
                        r->bottom *= scaling;
                }

                fFrame.left *= scaling;
                fFrame.top *= scaling;
                fFrame.right *= scaling;
                fFrame.bottom *= scaling;
        }
        else
        {
                Set(ERect(0, 0, 0, 0));
        }
}


ERegion&
ERegion::ScaleSelf(float scaling)
{
        Scale(scaling);
        return *this;
}


ERegion
ERegion::ScaleCopy(float scaling)
{
        ERegion aRegion(*this);
        aRegion.Scale(scaling);
        return aRegion;
}
[/code:1]
回复

使用道具 举报

 楼主| 发表于 2006-6-18 10:20:34 | 显示全部楼层
你的程序都加杂着docbook注释,看起来太复杂了。呵呵!
另写一个同名的文档不行吗?
例如你写的:Region.cpp,再写一个Region.cpp.doc不行吗?

你注释写的挺多的。
回复

使用道具 举报

发表于 2006-6-19 17:23:17 | 显示全部楼层
其实并不复杂,你看那个播放器的图,最后只剩下4个有效区而已
回复

使用道具 举报

 楼主| 发表于 2006-6-20 08:31:55 | 显示全部楼层
是啊,简单的4个区域,但写程序就不算少.

正在施工中....
回复

使用道具 举报

发表于 2006-6-20 23:19:56 | 显示全部楼层
[quote:29824d756b="asmcos"]你的程序都加杂着docbook注释,看起来太复杂了。呵呵!
另写一个同名的文档不行吗?
例如你写的:Region.cpp,再写一个Region.cpp.doc不行吗?

你注释写的挺多的。[/quote]

是为了能一次过自动生成开发手册和更改源码的时候同时能更新文档,
所以我选择了DocBook语法和写一个能浏览此种格式源码的sgml/xml察看器。

一般的整数坐标应用则把上述源码中的
regionLastA.Exclude(r)改为regionLastA.Exclude(r.InsetByCopy(-1, -1))
即可,即裁减的矩形相当于原矩形向外扩充1个单位。

其实关键代码是在 inline ERect* rect_exclude() 中,
对您来说,其它可能并非必要。
回复

使用道具 举报

 楼主| 发表于 2006-6-21 17:46:38 | 显示全部楼层
EGui裁减区域的计算工作基本完成,
看贴图,红色区域就是裁减口的各可视矩形,

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
回复

使用道具 举报

发表于 2006-9-8 13:22:04 | 显示全部楼层
计算一张同等大小的mask表,绘制的时候查询mask表,被覆盖(mask==1)的像素不绘制。在简单的情况下,mask可用扫描线记录替代。
回复

使用道具 举报

发表于 2006-9-12 13:41:55 | 显示全部楼层
为什么一定需要裁减矩形呢?

我尝试过的办法是:

1. 基于屏幕标记脏区域
2. 处理脏区域时计算所有与之有交叠的窗口
3. 按照Z序从下往上绘制
回复

使用道具 举报

发表于 2006-9-22 14:51:43 | 显示全部楼层
看lGUI的文档,写的很详细。

有一句话很受用:如果剪裁域是用RECT数组(或链表)来表示,A窗口被B窗口覆盖后,则剪裁域里的每个RECT最多被分割成4个RECT。所以,你只要针对每个RECT做剪裁就OK了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-3-29 15:20 , Processed in 0.114121 second(s), 13 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表