view anagram/vaclgui/agrect.cpp @ 15:f5acaf0c8a29

Don't cast through "volatile int". Causes a gcc warning nowadays. XXX: should put something else back here to frighten the optimizer
author David A. Holland
date Tue, 31 May 2022 01:00:55 -0400
parents 13d2b8934445
children
line wrap: on
line source

/*
 * AnaGram, A System for Syntax Directed Programming
 * Copyright 1997-2002 Parsifal Software. All Rights Reserved.
 * See the file COPYING for license and usage terms.
 *
 * agrect.cpp
 */

#include "agrect.hpp"


AgQuadrant opposite(AgQuadrant corner) {
  return (AgQuadrant) ((int) corner ^ 3);
}

AgRectangle::AgRectangle(RECT r) {
  pos = cint(r.left, r.top);
  sz = cint(r.right - r.left, r.bottom - r.top);
}

AgRectangle::AgRectangle(IWindow *w) : anchor(upperLeft) {
  pos = w->position();
  sz = w->size();
}

AgRectangle::AgRectangle(cint size_)
  : pos(0,0)
  , sz(size_)
  , anchor(upperLeft)
{}

AgRectangle::AgRectangle(cint loc, cint size_, AgQuadrant whichQuadrant)
  : pos(loc)
  , sz(size_)
  , anchor(whichQuadrant)
{
  switch (anchor) {
    case upperRight: pos.y -= sz.y; break;
    case upperLeft:  pos.y -= sz.y; /* fallthrough */
    case lowerLeft:  pos.x -= sz.x; break;
  }
}

cint AgRectangle::position(AgQuadrant whichCorner) {
  cint where = pos;
  switch (whichCorner) {
    case lowerLeft:  where.y += sz.y; break;
    case lowerRight: where.y += sz.y; /* fallthrough */
    case upperRight: where.x += sz.x; break;
  }
  return where;
}

AgRectangle &AgRectangle::setSize(cint s) {
  cint pos = position(anchor);
  sz = s;
  switch (anchor) {
    case upperRight: pos.y -= sz.y; break;
    case upperLeft:  pos.y -= sz.y; /* fallthrough */
    case lowerLeft:  pos.x -= sz.x; break;
  }
  return *this;
}

AgRectangle AgRectangle::intersection(AgRectangle &r) {
  cint loc = lrci(pos, r.pos);
  cint lr = ulci(pos+sz, r.pos + r.sz);
  lr = lrci(loc,lr);
  return AgRectangle(loc, lr - loc);
}

AgRectangle &AgRectangle::limit(cint size) {
  sz = ulci(sz, size);
  pos = ulci(pos, size - sz);
  pos = lrci(pos, cint(0, 0));
  return *this;
}

AgRectangle AgRectangle::desktop() {
  RECT r;
  SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
  AgRectangle rect(r);
  return rect;
}

int AgRectangle::operator < (const AgRectangle &r) const {
  if (pos < r.pos) {
    return 1;
  }
  if (r.pos > pos) {
    return 0;
  }
  return sz < r.sz;
}

LayoutRef::LayoutRef(AgRectangle &r) {
  int i;
  for (i = upperLeft; i <= lowerRight; i++) {
    AgQuadrant ic = (AgQuadrant) i;
    corner[ic] = r.position(ic);
  }
  stack.push(r);
}

int LayoutRef::overlap(AgRectangle &r) {
  int n = stack.size();
  int area = 0;
  while (n--) {
    area += r.intersection(stack[n]).area();
  }
  return area;
}

void LayoutRef::merge(AgRectangle &r) {
  stack.push(r);
  int i;
  for (i = upperLeft; i <= lowerRight; i++) {
    AgQuadrant ic = (AgQuadrant) i;
    cint rCorner = r.position(ic);
    switch (ic) {
      case upperLeft: {
        if (rCorner.y < corner[ic].y
          || rCorner.y == corner[ic].y && rCorner.x < corner[ic].x) {
          corner[ic] = rCorner;
        }
        break;
      }
      case upperRight: {
        if (rCorner.y < corner[ic].y
          || rCorner.y == corner[ic].y && rCorner.x > corner[ic].x) {
          corner[ic] = rCorner;
        }
        break;
      }
      case lowerLeft: {
        if (rCorner.y > corner[ic].y
          || rCorner.y == corner[ic].y && rCorner.x > corner[ic].x) {
          corner[ic] = rCorner;
        }
        break;
      }
      case lowerRight: {
        if (rCorner.y > corner[ic].y
          || rCorner.y == corner[ic].y && rCorner.x > corner[ic].x) {
          corner[ic] = rCorner;
        }
        break;
      }
    }
  }
}