/******************************************************************************/ /* Copyright (c) 1994 Vectaport, Inc. */ /* Copyright (c) 1990, 1991 Stanford University */ /* */ /* Permission to use, copy, modify, distribute, and sell this software and */ /* its documentation for any purpose is hereby granted without fee, provided */ /* that the above copyright notice appear in all copies and that both that */ /* copyright notice and this permission notice appear in supporting */ /* documentation, and that the names of the copyright holders not be used in */ /* advertising or publicity pertaining to distribution of the software */ /* without specific, written prior permission. The copyright holders make */ /* no representations about the suitability of this software for any purpose. */ /* It is provided "as is" without express or implied warranty. */ /* */ /* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS */ /* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. */ /* IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, */ /* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING */ /* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, */ /* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION */ /* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* */ /******************************************************************************/ /* * Picture class implementation. A Picture is a Graphic that contains other * Graphics. */ #include #include #include #include #include #include /*****************************************************************************/ Picture::Picture (Graphic* gr) : FullGraphic(gr) { _extent = nil; _kids = new UList(); } Picture::~Picture () { while (!_kids->IsEmpty()) { UList* cur = _kids->First(); _kids->Remove(cur); Graphic* g = graphic(cur); delete g; delete cur; } delete _kids; uncacheExtent(); } void Picture::First (Iterator& i) { i.SetValue(_kids->First()); } void Picture::Last (Iterator& i) { i.SetValue(_kids->Last()); } void Picture::Next (Iterator& i) { i.SetValue(Elem(i)->Next()); } void Picture::Prev (Iterator& i) { i.SetValue(Elem(i)->Prev()); } boolean Picture::Done (Iterator i) { return Elem(i) == _kids->End(); } boolean Picture::IsEmpty () { return _kids->IsEmpty(); } Graphic* Picture::GetGraphic (Iterator i) { return graphic(Elem(i)); } void Picture::SetGraphic (Graphic* g, Iterator& i) { i.SetValue(_kids->Find(g)); } void Picture::Append (Graphic* g0, Graphic* g1, Graphic* g2, Graphic* g3) { invalidateCachesGraphic(g0); _kids->Append(new UList(g0)); setParent(g0, this); if (g1 != nil) { invalidateCachesGraphic(g1); _kids->Append(new UList(g1)); setParent(g1, this); } if (g2 != nil) { invalidateCachesGraphic(g2); _kids->Append(new UList(g2)); setParent(g2, this); } if (g3 != nil) { invalidateCachesGraphic(g3); _kids->Append(new UList(g3)); setParent(g3, this); } uncacheExtent(); uncacheParents(); } void Picture::Prepend (Graphic* g0, Graphic* g1, Graphic* g2, Graphic* g3) { if (g3 != nil) { invalidateCachesGraphic(g3); _kids->Prepend(new UList(g3)); setParent(g3, this); } if (g2 != nil) { invalidateCachesGraphic(g2); _kids->Prepend(new UList(g2)); setParent(g2, this); } if (g1 != nil) { invalidateCachesGraphic(g1); _kids->Prepend(new UList(g1)); setParent(g1, this); } invalidateCachesGraphic(g0); _kids->Prepend(new UList(g0)); setParent(g0, this); uncacheExtent(); uncacheParents(); } void Picture::InsertBefore (Iterator i, Graphic* g) { invalidateCachesGraphic(g); Elem(i)->Append(new UList(g)); setParent(g, this); uncacheExtent(); uncacheParents(); } void Picture::InsertAfter (Iterator i, Graphic* g) { invalidateCachesGraphic(g); Elem(i)->Prepend(new UList(g)); setParent(g, this); uncacheExtent(); uncacheParents(); } void Picture::Remove (Graphic* g) { unsetParent(g); _kids->Delete(g); uncacheExtent(); uncacheParents(); } void Picture::Remove (Iterator& i) { UList* doomed = Elem(i); Graphic* g = graphic(doomed); Next(i); unsetParent(g); _kids->Remove(doomed); delete doomed; uncacheExtent(); uncacheParents(); } Graphic* Picture::FirstGraphicContaining (PointObj& pt) { if (Desensitized()) return nil; Iterator i; for (First(i); !Done(i); Next(i)) { Graphic* subgr = GetGraphic(i); if (subgr->Contains(pt)) { return subgr; } } return nil; } Graphic* Picture::LastGraphicContaining (PointObj& pt) { if (Desensitized()) return nil; Iterator i; for (Last(i); !Done(i); Prev(i)) { Graphic* subgr = GetGraphic(i); if (subgr->Contains(pt)) { return subgr; } } return nil; } Graphic* Picture::FirstGraphicIntersecting (BoxObj& b) { if (Desensitized()) return nil; Iterator i; for (First(i); !Done(i); Next(i)) { Graphic* subgr = GetGraphic(i); if (subgr->Intersects(b)) { return subgr; } } return nil; } Graphic* Picture::LastGraphicIntersecting (BoxObj& b) { if (Desensitized()) return nil; Iterator i; for (Last(i); !Done(i); Prev(i)) { Graphic* subgr = GetGraphic(i); if (subgr->Intersects(b)) { return subgr; } } return nil; } Graphic* Picture::FirstGraphicWithin (BoxObj& userb) { if (Desensitized()) return nil; Iterator i; BoxObj b; for (First(i); !Done(i); Next(i)) { Graphic* subgr = GetGraphic(i); if (subgr->Desensitized()) { return nil; } subgr->GetBox(b); if (b.Within(userb)) { return subgr; } } return nil; } Graphic* Picture::LastGraphicWithin (BoxObj& userb) { if (Desensitized()) return nil; Iterator i; BoxObj b; for (Last(i); !Done(i); Prev(i)) { Graphic* subgr = GetGraphic(i); if (subgr->Desensitized()) { return nil; } subgr->GetBox(b); if (b.Within(userb)) { return subgr; } } return nil; } void Picture::Bequeath () { Iterator i; for (First(i); !Done(i); Next(i)) { Graphic* gr = GetGraphic(i); concatGraphic(gr, gr, this, gr); } FullGraphic null; *((Graphic*) this) = null; } Graphic* Picture::Copy () { Iterator i; Picture* newPicture = new Picture(this); for (First(i); !Done(i); Next(i)) { newPicture->Append(GetGraphic(i)->Copy()); } return newPicture; } ClassId Picture::CompId () { return GRAPHIC_COMPS; } Graphic* Picture::graphic(UList* r) { return (Graphic*) (*r)(); } UList* Picture::Elem (Iterator i) { return (UList*) i.GetValue(); } void Picture::draw (Canvas* c, Graphic* gs) { Iterator i; FullGraphic gstemp; Transformer ttemp; gstemp.SetTransformer(&ttemp); for (First(i); !Done(i); Next(i)) { Graphic* gr = GetGraphic(i); concatGraphic(gr, gr, gs, &gstemp); drawGraphic(gr, c, &gstemp); } gstemp.SetTransformer(nil); /* to avoid deleting ttemp explicitly */ } void Picture::drawClipped ( Canvas* c, Coord l, Coord b, Coord r, Coord t, Graphic* gs ) { BoxObj box, clipBox(l, b, r, t); getBox(box, gs); if (clipBox.Intersects(box)) { Iterator i; FullGraphic gstemp; Transformer ttemp; gstemp.SetTransformer(&ttemp); for (First(i); !Done(i); Next(i)) { Graphic* gr = GetGraphic(i); concatGraphic(gr, gr, gs, &gstemp); drawClippedGraphic(gr, c, l, b, r, t, &gstemp); } gstemp.SetTransformer(nil); /* to avoid deleting ttemp explicitly */ } } void Picture::getExtent ( float& l, float& b, float& cx, float& cy, float& tol, Graphic* gs ) { Extent e; float right, top, dummy1, dummy2; if (extentCached()) { getCachedExtent(e._left, e._bottom, e._cx, e._cy, e._tol); } else { if (IsEmpty()) { l = b = cx = cy = tol = 0.0; return; } else { Iterator i; FullGraphic gstemp; Transformer ttemp; Extent te; gstemp.SetTransformer(&ttemp); First(i); Graphic* gr = GetGraphic(i); concatGSGraphic(gr, gr, gs, &gstemp); concatTransformerGraphic(gr, nil, gr->GetTransformer(), &ttemp); getExtentGraphic(gr, e._left,e._bottom,e._cx,e._cy,e._tol,&gstemp); for (Next(i); !Done(i); Next(i)) { gr = GetGraphic(i); concatGSGraphic(gr, gr, gs, &gstemp); concatTransformerGraphic(gr,nil, gr->GetTransformer(), &ttemp); getExtentGraphic( gr, te._left, te._bottom, te._cx, te._cy, te._tol, &gstemp ); e.Merge(te); } cacheExtent(e._left, e._bottom, e._cx, e._cy, e._tol); gstemp.SetTransformer(nil); // to avoid deleting ttemp explicitly } } right = 2*e._cx - e._left; top = 2*e._cy - e._bottom; transformRect(e._left, e._bottom, right, top, l, b, dummy1, dummy2, gs); transform(e._cx, e._cy, cx, cy, gs); tol = e._tol; } boolean Picture::contains (PointObj& po, Graphic* gs) { if (!IsEmpty()) { Iterator i; FullGraphic gstemp; Transformer ttemp; BoxObj b; getBox(b, gs); if (b.Contains(po)) { gstemp.SetTransformer(&ttemp); for (First(i); !Done(i); Next(i)) { Graphic* gr = GetGraphic(i); concatGraphic(gr, gr, gs, &gstemp); if (containsGraphic(gr, po, &gstemp)) { gstemp.SetTransformer(nil); return true; } } gstemp.SetTransformer(nil); /* to avoid deleting ttemp explicitly*/ } } return false; } boolean Picture::intersects (BoxObj& userb, Graphic* gs) { if (!IsEmpty()) { Iterator i; FullGraphic gstemp; Transformer ttemp; BoxObj b; getBox(b, gs); if (b.Intersects(userb)) { gstemp.SetTransformer(&ttemp); for (First(i); !Done(i); Next(i)) { Graphic* gr = GetGraphic(i); concatGraphic(gr, gr, gs, &gstemp); if (intersectsGraphic(gr, userb, &gstemp)) { gstemp.SetTransformer(nil); return true; } } gstemp.SetTransformer(nil); /* to avoid deleting ttemp explicitly*/ } } return false; } void Picture::getCachedExtent ( float& l, float& b, float& cx, float& cy, float& tol ) { l = _extent->_left; b = _extent->_bottom; cx = _extent->_cx; cy = _extent->_cy; tol = _extent->_tol; } boolean Picture::extentCached () { return _caching && _extent != nil; } void Picture::cacheExtent (float l, float b, float cx, float cy, float tol) { if (_caching) { uncacheExtent(); _extent = new Extent(l, b, cx, cy, tol); } } void Picture::uncacheExtent () { delete _extent; _extent = nil; } void Picture::uncacheChildren () { register UList* i; Graphic* subgr; for (i = _kids->First(); i != _kids->End(); i = i->Next()) { subgr = graphic(i); uncacheExtentGraphic(subgr); uncacheChildrenGraphic(subgr); } }