summaryrefslogtreecommitdiff
path: root/dw/types.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dw/types.cc')
-rw-r--r--dw/types.cc367
1 files changed, 367 insertions, 0 deletions
diff --git a/dw/types.cc b/dw/types.cc
new file mode 100644
index 0000000..3962d97
--- /dev/null
+++ b/dw/types.cc
@@ -0,0 +1,367 @@
+/*
+ * RTFL (originally part of dillo)
+ *
+ * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version; with the following exception:
+ *
+ * The copyright holders of RTFL give you permission to link this file
+ * statically or dynamically against all versions of the graphviz
+ * library, which are published by AT&T Corp. under one of the following
+ * licenses:
+ *
+ * - Common Public License version 1.0 as published by International
+ * Business Machines Corporation (IBM), or
+ * - Eclipse Public License version 1.0 as published by the Eclipse
+ * Foundation.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+
+#include "core.hh"
+#include "../lout/msg.h"
+
+using namespace lout;
+
+namespace dw {
+namespace core {
+
+Rectangle::Rectangle (int x, int y, int width, int height)
+{
+ this->x = x;
+ this->y = y;
+ this->width = width;
+ this->height = height;
+}
+
+/*
+ * Draw rectangle in view relative to point (x,y).
+ */
+void Rectangle::draw (core::View *view, core::style::Style *style, int x,int y)
+{
+ const bool filled = false;
+
+ view->drawRectangle(style->color, core::style::Color::SHADING_NORMAL,filled,
+ x + this->x, y + this->y, this->width, this->height);
+}
+
+/**
+ * Return whether this rectangle and otherRect intersect. If yes,
+ * return the intersection rectangle in dest.
+ */
+bool Rectangle::intersectsWith (Rectangle *otherRect, Rectangle *dest)
+{
+ bool doIntersect =
+ this->x < otherRect->x + otherRect->width &&
+ this->y < otherRect->y + otherRect->height &&
+ otherRect->x < this->x + this->width &&
+ otherRect->y < this->y + this->height;
+
+ if (doIntersect) {
+ dest->x = misc::max(this->x, otherRect->x);
+ dest->y = misc::max(this->y, otherRect->y);
+ dest->width = misc::min(this->x + this->width,
+ otherRect->x + otherRect->width) - dest->x;
+ dest->height = misc::min(this->y + this->height,
+ otherRect->y + otherRect->height) - dest->y;
+ } else {
+ dest->x = dest->y = dest->width = dest->height = 0;
+ }
+
+ return doIntersect;
+}
+
+/*
+ * Return whether this is a subset of otherRect.
+ */
+bool Rectangle::isSubsetOf (Rectangle *otherRect)
+{
+ return
+ x >= otherRect->x &&
+ y >= otherRect->y &&
+ x + width <= otherRect->x + otherRect->width &&
+ y + height <= otherRect->y + otherRect->height;
+}
+
+bool Rectangle::isPointWithin (int x, int y)
+{
+ return
+ x >= this->x && y >= this->y &&
+ x < this->x + width && y < this->y + height;
+}
+
+// ----------------------------------------------------------------------
+
+Circle::Circle (int x, int y, int radius)
+{
+ this->x = x;
+ this->y = y;
+ this->radius = radius;
+}
+
+/*
+ * Draw circle in view relative to point (x,y).
+ */
+void Circle::draw (core::View *view, core::style::Style *style, int x, int y)
+{
+ const bool filled = false;
+
+ view->drawArc(style->color, core::style::Color::SHADING_NORMAL, filled,
+ x + this->x, y + this->y, 2 * this->radius, 2 * this->radius,
+ 0, 360);
+}
+
+bool Circle::isPointWithin (int x, int y)
+{
+ return
+ (x - this->x) * (x - this->x) + (y - this->y) * (y - this->y)
+ <= radius * radius;
+}
+
+// ----------------------------------------------------------------------
+
+Polygon::Polygon ()
+{
+ points = new misc::SimpleVector<Point> (8);
+ minx = miny = 0xffffff;
+ maxx = maxy = -0xffffff;
+}
+
+Polygon::~Polygon ()
+{
+ delete points;
+}
+
+/*
+ * Draw polygon in view relative to point (x,y).
+ */
+void Polygon::draw (core::View *view, core::style::Style *style, int x, int y)
+{
+ if (points->size()) {
+ int i;
+ const bool filled = false, convex = false;
+ Point *pointArray = (Point *)malloc(points->size()*sizeof(struct Point));
+
+ for (i = 0; i < points->size(); i++) {
+ pointArray[i].x = x + points->getRef(i)->x;
+ pointArray[i].y = y + points->getRef(i)->y;
+ }
+ view->drawPolygon(style->color, core::style::Color::SHADING_NORMAL,
+ filled, convex, pointArray, i);
+ free(pointArray);
+ }
+}
+
+void Polygon::addPoint (int x, int y)
+{
+ points->increase ();
+ points->getRef(points->size () - 1)->x = x;
+ points->getRef(points->size () - 1)->y = y;
+
+ minx = misc::min(minx, x);
+ miny = misc::min(miny, y);
+ maxx = misc::max(maxx, x);
+ maxy = misc::max(maxy, y);
+}
+
+/**
+ * \brief Return, whether the line, limited by (ax1, ay1) and (ax2, ay2),
+ * crosses the unlimited line, determined by two points (bx1, by1) and
+ * (bx2, by2).
+ */
+bool Polygon::linesCross0(int ax1, int ay1, int ax2, int ay2,
+ int bx1, int by1, int bx2, int by2)
+{
+ /** TODO Some more description */
+ // If the scalar product is 0, it means that one point is on the second
+ // line, so we check for <= 0, not < 0.
+ int z1 = zOfVectorProduct (ax1 - bx1, ay1 - by1, bx2 - bx1, by2 - by1);
+ int z2 = zOfVectorProduct (ax2 - bx1, ay2 - by1, bx2 - bx1, by2 - by1);
+
+ return (z1 <= 0 && z2 >= 0) || (z1 >= 0 && z2 <= 0);
+}
+
+/**
+ * \brief Return, whether the line, limited by (ax1, ay1) and (ax2, ay2),
+ * crosses the line, limited by (bx1, by1) and (bx2, by2).
+ */
+bool Polygon::linesCross(int ax1, int ay1, int ax2, int ay2,
+ int bx1, int by1, int bx2, int by2)
+{
+ bool cross =
+ linesCross0 (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2) &&
+ linesCross0 (bx1, by1, bx2, by2, ax1, ay1, ax2, ay2);
+ _MSG("(%d, %d) - (%d, %d) and (%d, %d) - (%d, %d) cross? %s.\n",
+ ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, cross ? "Yes" : "No");
+ return cross;
+}
+
+bool Polygon::isPointWithin (int x, int y)
+{
+ if (points->size () < 3 ||
+ (x < minx || x > maxx || y < miny || y >= maxy))
+ return false;
+ else {
+ int numCrosses = 0;
+ for (int i = 0; i < points->size () - 1; i++) {
+ if (linesCross (minx - 1, miny - 1, x, y,
+ points->getRef(i)->x, points->getRef(i)->y,
+ points->getRef(i + 1)->x, points->getRef(i + 1)->y))
+ numCrosses++;
+ }
+ if (linesCross (minx - 1, miny - 1, x, y,
+ points->getRef(points->size () - 1)->x,
+ points->getRef(points->size () - 1)->y,
+ points->getRef(0)->x, points->getRef(0)->y))
+ numCrosses++;
+
+ return numCrosses % 2 == 1;
+ }
+}
+
+Region::Region()
+{
+ rectangleList = new container::typed::List <Rectangle> (true);
+}
+
+Region::~Region()
+{
+ delete rectangleList;
+}
+
+/**
+ * \brief Add a rectangle to the region and combine it with
+ * existing rectangles if possible.
+ * The number of rectangles is forced to be less than 16
+ * by combining excessive rectangles.
+ */
+void Region::addRectangle (Rectangle *rPointer)
+{
+ container::typed::Iterator <Rectangle> it;
+ Rectangle *r = new Rectangle (rPointer->x, rPointer->y,
+ rPointer->width, rPointer->height);
+
+ for (it = rectangleList->iterator (); it.hasNext (); ) {
+ Rectangle *ownRect = it.getNext ();
+
+ int combinedHeight =
+ misc::max(r->y + r->height, ownRect->y + ownRect->height) -
+ misc::min(r->y, ownRect->y);
+ int combinedWidth =
+ misc::max(r->x + r->width, ownRect->x + ownRect->width) -
+ misc::min(r->x, ownRect->x);
+
+ if (rectangleList->size() >= 16 ||
+ combinedWidth * combinedHeight <=
+ ownRect->width * ownRect->height + r->width * r->height) {
+
+ r->x = misc::min(r->x, ownRect->x);
+ r->y = misc::min(r->y, ownRect->y);
+ r->width = combinedWidth;
+ r->height = combinedHeight;
+
+ rectangleList->removeRef (ownRect);
+ }
+ }
+
+ rectangleList->append (r);
+}
+
+Content::Type Content::maskForSelection (bool followReferences)
+{
+ Content::Type widgetMask = (Content::Type)
+ (Content::WIDGET_IN_FLOW |
+ (followReferences ? Content::WIDGET_OOF_REF : Content::WIDGET_OOF_CONT));
+ return (Content::Type)(Content::SELECTION_CONTENT | widgetMask);
+}
+
+void Content::intoStringBuffer(Content *content, misc::StringBuffer *sb)
+{
+ switch(content->type) {
+ case START:
+ sb->append ("<start>");
+ break;
+ case END:
+ sb->append ("<end>");
+ break;
+ case TEXT:
+ sb->append ("\"");
+ sb->append (content->text);
+ sb->append ("\"");
+ break;
+ case WIDGET_IN_FLOW:
+ sb->append ("<widget in flow: ");
+ sb->appendPointer (content->widget);
+ sb->append (" (");
+ sb->append (content->widget->getClassName());
+ sb->append (")>");
+ break;
+ case WIDGET_OOF_REF:
+ sb->append ("<widget oof ref: ");
+ sb->appendPointer (content->widget);
+ sb->append (" (");
+ sb->append (content->widget->getClassName());
+ sb->append (")>");
+ break;
+ case WIDGET_OOF_CONT:
+ sb->append ("<widget oof cont: ");
+ sb->appendPointer (content->widget);
+ sb->append (" (");
+ sb->append (content->widget->getClassName());
+ sb->append (")>");
+ break;
+ case BREAK:
+ sb->append ("<break>");
+ break;
+ default:
+ sb->append ("<");
+ sb->appendInt (content->type);
+ sb->append ("?>");
+ break;
+ }
+}
+
+void Content::maskIntoStringBuffer(Type mask, misc::StringBuffer *sb)
+{
+ sb->append ((mask & START) ? "st" : "--");
+ sb->append (":");
+ sb->append ((mask & END) ? "en" : "--");
+ sb->append (":");
+ sb->append ((mask & TEXT) ? "tx" : "--");
+ sb->append (":");
+ sb->append ((mask & WIDGET_IN_FLOW) ? "wf" : "--");
+ sb->append (":");
+ sb->append ((mask & WIDGET_OOF_REF) ? "Wr" : "--");
+ sb->append (":");
+ sb->append ((mask & WIDGET_OOF_CONT) ? "Wc" : "--");
+ sb->append (":");
+ sb->append ((mask & BREAK) ? "br" : "--");
+}
+
+void Content::print (Content *content)
+{
+ misc::StringBuffer sb;
+ intoStringBuffer (content, &sb);
+ printf ("%s", sb.getChars ());
+}
+
+void Content::printMask (Type mask)
+{
+ misc::StringBuffer sb;
+ maskIntoStringBuffer (mask, &sb);
+ printf ("%s", sb.getChars ());
+}
+
+} // namespace core
+} // namespace dw