diff options
Diffstat (limited to 'kviewshell/plugins/djvu/libdjvu/GRect.cpp')
-rw-r--r-- | kviewshell/plugins/djvu/libdjvu/GRect.cpp | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/kviewshell/plugins/djvu/libdjvu/GRect.cpp b/kviewshell/plugins/djvu/libdjvu/GRect.cpp new file mode 100644 index 00000000..1ac0a87c --- /dev/null +++ b/kviewshell/plugins/djvu/libdjvu/GRect.cpp @@ -0,0 +1,458 @@ +//C- -*- C++ -*- +//C- ------------------------------------------------------------------- +//C- DjVuLibre-3.5 +//C- Copyright (c) 2002 Leon Bottou and Yann Le Cun. +//C- Copyright (c) 2001 AT&T +//C- +//C- This software is subject to, and may be distributed under, the +//C- GNU General Public License, Version 2. The license should have +//C- accompanied the software or you may obtain a copy of the license +//C- from the Free Software Foundation at http://www.fsf.org . +//C- +//C- This program is distributed in the hope that it will be useful, +//C- but WITHOUT ANY WARRANTY; without even the implied warranty of +//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//C- GNU General Public License for more details. +//C- +//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library +//C- distributed by Lizardtech Software. On July 19th 2002, Lizardtech +//C- Software authorized us to replace the original DjVu(r) Reference +//C- Library notice by the following text (see doc/lizard2002.djvu): +//C- +//C- ------------------------------------------------------------------ +//C- | DjVu (r) Reference Library (v. 3.5) +//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved. +//C- | The DjVu Reference Library is protected by U.S. Pat. No. +//C- | 6,058,214 and patents pending. +//C- | +//C- | This software is subject to, and may be distributed under, the +//C- | GNU General Public License, Version 2. The license should have +//C- | accompanied the software or you may obtain a copy of the license +//C- | from the Free Software Foundation at http://www.fsf.org . +//C- | +//C- | The computer code originally released by LizardTech under this +//C- | license and unmodified by other parties is deemed "the LIZARDTECH +//C- | ORIGINAL CODE." Subject to any third party intellectual property +//C- | claims, LizardTech grants recipient a worldwide, royalty-free, +//C- | non-exclusive license to make, use, sell, or otherwise dispose of +//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the +//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU +//C- | General Public License. This grant only confers the right to +//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to +//C- | the extent such infringement is reasonably necessary to enable +//C- | recipient to make, have made, practice, sell, or otherwise dispose +//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to +//C- | any greater extent that may be necessary to utilize further +//C- | modifications or combinations. +//C- | +//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY +//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF +//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +//C- +------------------------------------------------------------------ +// +// $Id: GRect.cpp,v 1.10 2003/11/07 22:08:21 leonb Exp $ +// $Name: release_3_5_15 $ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#if NEED_GNUG_PRAGMAS +# pragma implementation +#endif + +// -- Implementation of class GRect and GRectMapper +// - Author: Leon Bottou, 05/1997 + + +#include "GRect.h" +#include "GException.h" + + +#ifdef HAVE_NAMESPACES +namespace DJVU { +# ifdef NOT_DEFINED // Just to fool emacs c++ mode +} +#endif +#endif + +// -- Local utilities + +static inline int +imin(int x, int y) +{ + if (x < y) + return x; + else + return y; +} + +static inline int +imax(int x, int y) +{ + if (x > y) + return x; + else + return y; +} + +static inline void +iswap(int &x, int &y) +{ + int tmp = x; x = y; y = tmp; +} + +// -- Class GRect + +int +operator==(const GRect & r1, const GRect & r2) +{ + int isempty1 = r1.isempty(); + int isempty2 = r2.isempty(); + if (isempty1 || isempty2) + if (isempty1 && isempty2) + return 1; + if ( r1.xmin==r2.xmin && r1.xmax==r2.xmax + && r1.ymin==r2.ymin && r1.ymax==r2.ymax ) + return 1; + return 0; +} + +int +GRect::inflate(int dx, int dy) +{ + xmin -= dx; + xmax += dx; + ymin -= dy; + ymax += dy; + if (! isempty()) + return 1; + xmin = ymin = xmax = ymax = 0; + return 0; +} + +int +GRect::translate(int dx, int dy) +{ + xmin += dx; + xmax += dx; + ymin += dy; + ymax += dy; + if (! isempty()) + return 1; + xmin = ymin = xmax = ymax = 0; + return 0; +} + +int +GRect::intersect(const GRect &rect1, const GRect &rect2) +{ + xmin = imax(rect1.xmin, rect2.xmin); + xmax = imin(rect1.xmax, rect2.xmax); + ymin = imax(rect1.ymin, rect2.ymin); + ymax = imin(rect1.ymax, rect2.ymax); + if (! isempty()) + return 1; + xmin = ymin = xmax = ymax = 0; + return 0; +} + +int +GRect::recthull(const GRect &rect1, const GRect &rect2) +{ + if (rect1.isempty()) + { + xmin = rect2.xmin; + xmax = rect2.xmax; + ymin = rect2.ymin; + ymax = rect2.ymax; + return !isempty(); + } + if (rect2.isempty()) + { + xmin = rect1.xmin; + xmax = rect1.xmax; + ymin = rect1.ymin; + ymax = rect1.ymax; + return !isempty(); + } + xmin = imin(rect1.xmin, rect2.xmin); + xmax = imax(rect1.xmax, rect2.xmax); + ymin = imin(rect1.ymin, rect2.ymin); + ymax = imax(rect1.ymax, rect2.ymax); + return 1; +} + +int +GRect::contains(const GRect & rect) const +{ + GRect tmp_rect; + tmp_rect.intersect(*this, rect); + return tmp_rect==rect; +} + +void +GRect::scale(float factor) +{ + xmin = (int)(((float)xmin) * factor); + ymin = (int)(((float)ymin) * factor); + xmax = (int)(((float)xmax) * factor); + ymax = (int)(((float)ymax) * factor); +} + +void +GRect::scale(float xfactor, float yfactor) +{ + xmin = (int)(((float)xmin) * xfactor); + ymin = (int)(((float)ymin) * yfactor); + xmax = (int)(((float)xmax) * xfactor); + ymax = (int)(((float)ymax) * yfactor); +} +// -- Class GRatio + + +inline +GRectMapper::GRatio::GRatio() + : p(0), q(1) +{ +} + +inline +GRectMapper::GRatio::GRatio(int p, int q) + : p(p), q(q) +{ + if (q == 0) + G_THROW( ERR_MSG("GRect.div_zero") ); + if (p == 0) + q = 1; + if (q < 0) + { + p = -p; + q = -q; + } + int gcd = 1; + int g1 = p; + int g2 = q; + if (g1 > g2) + { + gcd = g1; + g1 = g2; + g2 = gcd; + } + while (g1 > 0) + { + gcd = g1; + g1 = g2 % g1; + g2 = gcd; + } + p /= gcd; + q /= gcd; +} + + +#ifdef HAVE_LONG_LONG_INT +#define llint_t long long int +#else +#define llint_t long int +#endif + +inline int +operator*(int n, GRectMapper::GRatio r ) +{ + /* [LB] -- This computation is carried out with integers and + rational numbers because it must be exact. Some lizard changed + it to double and this is wrong. I suspect they did so because + they encountered overflow issues. Let's use long long ints. */ + llint_t x = (llint_t) n * (llint_t) r.p; + if (x >= 0) + return ((r.q/2 + x) / r.q); + else + return - ((r.q/2 - x) / r.q); +} + +inline int +operator/(int n, GRectMapper::GRatio r ) +{ + /* [LB] -- See comment in operator*() above. */ + llint_t x = (llint_t) n * (llint_t) r.q; + if (x >= 0) + return ((r.p/2 + x) / r.p); + else + return - ((r.p/2 - x) / r.p); +} + + +// -- Class GRectMapper + +#define MIRRORX 1 +#define MIRRORY 2 +#define SWAPXY 4 + + +GRectMapper::GRectMapper() +: rectFrom(0,0,1,1), + rectTo(0,0,1,1), + code(0) +{ + +} + +void +GRectMapper::clear() +{ + rectFrom = GRect(0,0,1,1); + rectTo = GRect(0,0,1,1); + code = 0; +} + +void +GRectMapper::set_input(const GRect &rect) +{ + if (rect.isempty()) + G_THROW( ERR_MSG("GRect.empty_rect1") ); + rectFrom = rect; + if (code & SWAPXY) + { + iswap(rectFrom.xmin, rectFrom.ymin); + iswap(rectFrom.xmax, rectFrom.ymax); + } + rw = rh = GRatio(); +} + +void +GRectMapper::set_output(const GRect &rect) +{ + if (rect.isempty()) + G_THROW( ERR_MSG("GRect.empty_rect2") ); + rectTo = rect; + rw = rh = GRatio(); +} + +void +GRectMapper::rotate(int count) +{ + int oldcode = code; + switch (count & 0x3) + { + case 1: + code ^= (code & SWAPXY) ? MIRRORY : MIRRORX; + code ^= SWAPXY; + break; + case 2: + code ^= (MIRRORX|MIRRORY); + break; + case 3: + code ^= (code & SWAPXY) ? MIRRORX : MIRRORY; + code ^= SWAPXY; + break; + } + if ((oldcode ^ code) & SWAPXY) + { + iswap(rectFrom.xmin, rectFrom.ymin); + iswap(rectFrom.xmax, rectFrom.ymax); + rw = rh = GRatio(); + } +} + +void +GRectMapper::mirrorx() +{ + code ^= MIRRORX; +} + +void +GRectMapper::mirrory() +{ + code ^= MIRRORY; +} + +void +GRectMapper::precalc() +{ + if (rectTo.isempty() || rectFrom.isempty()) + G_THROW( ERR_MSG("GRect.empty_rect3") ); + rw = GRatio(rectTo.width(), rectFrom.width()); + rh = GRatio(rectTo.height(), rectFrom.height()); +} + +void +GRectMapper::map(int &x, int &y) +{ + int mx = x; + int my = y; + // precalc + if (! (rw.p && rh.p)) + precalc(); + // swap and mirror + if (code & SWAPXY) + iswap(mx,my); + if (code & MIRRORX) + mx = rectFrom.xmin + rectFrom.xmax - mx; + if (code & MIRRORY) + my = rectFrom.ymin + rectFrom.ymax - my; + // scale and translate + x = rectTo.xmin + (mx - rectFrom.xmin) * rw; + y = rectTo.ymin + (my - rectFrom.ymin) * rh; +} + +void +GRectMapper::unmap(int &x, int &y) +{ + // precalc + if (! (rw.p && rh.p)) + precalc(); + // scale and translate + int mx = rectFrom.xmin + (x - rectTo.xmin) / rw; + int my = rectFrom.ymin + (y - rectTo.ymin) / rh; + // mirror and swap + if (code & MIRRORX) + mx = rectFrom.xmin + rectFrom.xmax - mx; + if (code & MIRRORY) + my = rectFrom.ymin + rectFrom.ymax - my; + if (code & SWAPXY) + iswap(mx,my); + x = mx; + y = my; +} + +void +GRectMapper::map(GRect &rect) +{ + map(rect.xmin, rect.ymin); + map(rect.xmax, rect.ymax); + if (rect.xmin >= rect.xmax) + iswap(rect.xmin, rect.xmax); + if (rect.ymin >= rect.ymax) + iswap(rect.ymin, rect.ymax); +} + +void +GRectMapper::unmap(GRect &rect) +{ + unmap(rect.xmin, rect.ymin); + unmap(rect.xmax, rect.ymax); + if (rect.xmin >= rect.xmax) + iswap(rect.xmin, rect.xmax); + if (rect.ymin >= rect.ymax) + iswap(rect.ymin, rect.ymax); +} + +GRect +GRectMapper::get_input() +{ + return rectFrom; +} + +GRect +GRectMapper::get_output() +{ + return rectTo; +} + + +#ifdef HAVE_NAMESPACES +} +# ifndef NOT_USING_DJVU_NAMESPACE +using namespace DJVU; +# endif +#endif |