Fix potential UAF in ConcatInPlace.
[pdfium.git] / core / src / fxcrt / fx_basic_coords.cpp
index 47204e0..8e7bb3e 100644 (file)
-// Copyright 2014 PDFium Authors. All rights reserved.\r
-// Use of this source code is governed by a BSD-style license that can be\r
-// found in the LICENSE file.\r
\r
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
-\r
-#include "../../include/fxcrt/fx_ext.h"\r
-void FX_RECT::Normalize()\r
-{\r
-    if (left > right) {\r
-        int temp = left;\r
-        left = right;\r
-        right = temp;\r
-    }\r
-    if (top > bottom) {\r
-        int temp = top;\r
-        top = bottom;\r
-        bottom = temp;\r
-    }\r
-}\r
-void FX_RECT::Intersect(const FX_RECT& src)\r
-{\r
-    FX_RECT src_n = src;\r
-    src_n.Normalize();\r
-    Normalize();\r
-    left = left > src_n.left ? left : src_n.left;\r
-    top = top > src_n.top ? top : src_n.top;\r
-    right = right < src_n.right ? right : src_n.right;\r
-    bottom = bottom < src_n.bottom ? bottom : src_n.bottom;\r
-    if (left > right || top > bottom) {\r
-        left = top = right = bottom = 0;\r
-    }\r
-}\r
-void FX_RECT::Union(const FX_RECT& other_rect)\r
-{\r
-    Normalize();\r
-    FX_RECT other = other_rect;\r
-    other.Normalize();\r
-    left = left < other.left ? left : other.left;\r
-    right = right > other.right ? right : other.right;\r
-    bottom = bottom > other.bottom ? bottom : other.bottom;\r
-    top = top < other.top ? top : other.top;\r
-}\r
-FX_BOOL GetIntersection(FX_FLOAT low1, FX_FLOAT high1, FX_FLOAT low2, FX_FLOAT high2,\r
-                        FX_FLOAT& interlow, FX_FLOAT& interhigh)\r
-{\r
-    if (low1 >= high2 || low2 >= high1) {\r
-        return FALSE;\r
-    }\r
-    interlow = low1 > low2 ? low1 : low2;\r
-    interhigh = high1 > high2 ? high2 : high1;\r
-    return TRUE;\r
-}\r
-extern "C" int FXSYS_round(FX_FLOAT d)\r
-{\r
-    int iRet = 0;\r
-    if (d >= 0.0f) {\r
-        iRet = (int)(d + 0.5f);\r
-        if (iRet >= 0) {\r
-            return iRet;\r
-        }\r
-        return -iRet;\r
-    }\r
-    return (int)(d - 0.5f);\r
-}\r
-CFX_FloatRect::CFX_FloatRect(const FX_RECT& rect)\r
-{\r
-    left = (FX_FLOAT)(rect.left);\r
-    right = (FX_FLOAT)(rect.right);\r
-    bottom = (FX_FLOAT)(rect.top);\r
-    top = (FX_FLOAT)(rect.bottom);\r
-}\r
-void CFX_FloatRect::Normalize()\r
-{\r
-    FX_FLOAT temp;\r
-    if (left > right) {\r
-        temp = left;\r
-        left = right;\r
-        right = temp;\r
-    }\r
-    if (bottom > top) {\r
-        temp = top;\r
-        top = bottom;\r
-        bottom = temp;\r
-    }\r
-}\r
-void CFX_FloatRect::Intersect(const CFX_FloatRect& other_rect)\r
-{\r
-    Normalize();\r
-    CFX_FloatRect other = other_rect;\r
-    other.Normalize();\r
-    left = left > other.left ? left : other.left;\r
-    right = right < other.right ? right : other.right;\r
-    bottom = bottom > other.bottom ? bottom : other.bottom;\r
-    top = top < other.top ? top : other.top;\r
-    if (left > right || bottom > top) {\r
-        left = right = bottom = top = 0;\r
-    }\r
-}\r
-void CFX_FloatRect::Union(const CFX_FloatRect& other_rect)\r
-{\r
-    Normalize();\r
-    CFX_FloatRect other = other_rect;\r
-    other.Normalize();\r
-    left = left < other.left ? left : other.left;\r
-    right = right > other.right ? right : other.right;\r
-    bottom = bottom < other.bottom ? bottom : other.bottom;\r
-    top = top > other.top ? top : other.top;\r
-}\r
-void CFX_FloatRect::Transform(const CFX_Matrix* pMatrix)\r
-{\r
-    pMatrix->TransformRect(left, right, top, bottom);\r
-}\r
-int CFX_FloatRect::Substract4(CFX_FloatRect& s, CFX_FloatRect* pRects)\r
-{\r
-    Normalize();\r
-    s.Normalize();\r
-    int nRects = 0;\r
-    CFX_FloatRect rects[4];\r
-    if (left < s.left) {\r
-        rects[nRects].left = left;\r
-        rects[nRects].right = s.left;\r
-        rects[nRects].bottom = bottom;\r
-        rects[nRects].top = top;\r
-        nRects ++;\r
-    }\r
-    if (s.left < right && s.top < top) {\r
-        rects[nRects].left = s.left;\r
-        rects[nRects].right = right;\r
-        rects[nRects].bottom = s.top;\r
-        rects[nRects].top = top;\r
-        nRects ++;\r
-    }\r
-    if (s.top > bottom && s.right < right) {\r
-        rects[nRects].left = s.right;\r
-        rects[nRects].right = right;\r
-        rects[nRects].bottom = bottom;\r
-        rects[nRects].top = s.top;\r
-        nRects ++;\r
-    }\r
-    if (s.bottom > bottom) {\r
-        rects[nRects].left = s.left;\r
-        rects[nRects].right = s.right;\r
-        rects[nRects].bottom = bottom;\r
-        rects[nRects].top = s.bottom;\r
-        nRects ++;\r
-    }\r
-    if (nRects == 0) {\r
-        return 0;\r
-    }\r
-    for (int i = 0; i < nRects; i ++) {\r
-        pRects[i] = rects[i];\r
-        pRects[i].Intersect(*this);\r
-    }\r
-    return nRects;\r
-}\r
-FX_RECT CFX_FloatRect::GetOutterRect() const\r
-{\r
-    CFX_FloatRect rect1 = *this;\r
-    FX_RECT rect;\r
-    rect.left = (int)FXSYS_floor(rect1.left);\r
-    rect.right = (int)FXSYS_ceil(rect1.right);\r
-    rect.top = (int)FXSYS_floor(rect1.bottom);\r
-    rect.bottom = (int)FXSYS_ceil(rect1.top);\r
-    rect.Normalize();\r
-    return rect;\r
-}\r
-FX_RECT CFX_FloatRect::GetInnerRect() const\r
-{\r
-    CFX_FloatRect rect1 = *this;\r
-    FX_RECT rect;\r
-    rect.left = (int)FXSYS_ceil(rect1.left);\r
-    rect.right = (int)FXSYS_floor(rect1.right);\r
-    rect.top = (int)FXSYS_ceil(rect1.bottom);\r
-    rect.bottom = (int)FXSYS_floor(rect1.top);\r
-    rect.Normalize();\r
-    return rect;\r
-}\r
-static void _MatchFloatRange(FX_FLOAT f1, FX_FLOAT f2, int& i1, int& i2)\r
-{\r
-    int length = (int)FXSYS_ceil(f2 - f1);\r
-    int i1_1 = (int)FXSYS_floor(f1);\r
-    int i1_2 = (int)FXSYS_ceil(f1);\r
-    FX_FLOAT error1 = f1 - i1_1 + (FX_FLOAT)FXSYS_fabs(f2 - i1_1 - length);\r
-    FX_FLOAT error2 = i1_2 - f1 + (FX_FLOAT)FXSYS_fabs(f2 - i1_2 - length);\r
-    i1 = (error1 > error2) ? i1_2 : i1_1;\r
-    i2 = i1 + length;\r
-}\r
-FX_RECT CFX_FloatRect::GetClosestRect() const\r
-{\r
-    CFX_FloatRect rect1 = *this;\r
-    FX_RECT rect;\r
-    _MatchFloatRange(rect1.left, rect1.right, rect.left, rect.right);\r
-    _MatchFloatRange(rect1.bottom, rect1.top, rect.top, rect.bottom);\r
-    rect.Normalize();\r
-    return rect;\r
-}\r
-FX_BOOL CFX_FloatRect::Contains(const CFX_FloatRect& other_rect) const\r
-{\r
-    CFX_FloatRect n1 = *this;\r
-    n1.Normalize();\r
-    CFX_FloatRect n2 = other_rect;\r
-    n2.Normalize();\r
-    if (n2.left >= n1.left && n2.right <= n1.right && n2.bottom >= n1.bottom && n2.top <= n1.top) {\r
-        return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
-FX_BOOL CFX_FloatRect::Contains(FX_FLOAT x, FX_FLOAT y) const\r
-{\r
-    CFX_FloatRect n1 = *this;\r
-    n1.Normalize();\r
-    return x <= n1.right && x >= n1.left && y <= n1.top && y >= n1.bottom;\r
-}\r
-void CFX_FloatRect::UpdateRect(FX_FLOAT x, FX_FLOAT y)\r
-{\r
-    if (left > x) {\r
-        left = x;\r
-    }\r
-    if (right < x) {\r
-        right = x;\r
-    }\r
-    if (bottom > y) {\r
-        bottom = y;\r
-    }\r
-    if (top < y) {\r
-        top = y;\r
-    }\r
-}\r
-CFX_FloatRect CFX_FloatRect::GetBBox(const CFX_FloatPoint* pPoints, int nPoints)\r
-{\r
-    if (nPoints == 0) {\r
-        return CFX_FloatRect();\r
-    }\r
-    FX_FLOAT min_x = pPoints->x, max_x = pPoints->x, min_y = pPoints->y, max_y = pPoints->y;\r
-    for (int i = 1; i < nPoints; i ++) {\r
-        if (min_x > pPoints[i].x) {\r
-            min_x = pPoints[i].x;\r
-        }\r
-        if (max_x < pPoints[i].x) {\r
-            max_x = pPoints[i].x;\r
-        }\r
-        if (min_y > pPoints[i].y) {\r
-            min_y = pPoints[i].y;\r
-        }\r
-        if (max_y < pPoints[i].y) {\r
-            max_y = pPoints[i].y;\r
-        }\r
-    }\r
-    return CFX_FloatRect(min_x, min_y, max_x, max_y);\r
-}\r
-void CFX_Matrix::Set(FX_FLOAT a, FX_FLOAT b, FX_FLOAT c, FX_FLOAT d, FX_FLOAT e, FX_FLOAT f)\r
-{\r
-    this->a = a;\r
-    this->b = b;\r
-    this->c = c;\r
-    this->d = d;\r
-    this->e = e;\r
-    this->f = f;\r
-}\r
-void CFX_Matrix::Set(const FX_FLOAT n[6])\r
-{\r
-    FXSYS_memcpy32((void*)this, &n, sizeof(CFX_Matrix));\r
-}\r
-void CFX_Matrix::SetReverse(const CFX_Matrix &m)\r
-{\r
-    FX_FLOAT i = m.a * m.d - m.b * m.c;\r
-    if (FXSYS_fabs(i) == 0) {\r
-        return;\r
-    }\r
-    FX_FLOAT j = -i;\r
-    a = m.d / i;\r
-    b = m.b / j;\r
-    c = m.c / j;\r
-    d = m.a / i;\r
-    e = (m.c * m.f - m.d * m.e) / i;\r
-    f = (m.a * m.f - m.b * m.e) / j;\r
-}\r
-static void FXCRT_Matrix_Concat(CFX_Matrix &m, const CFX_Matrix &m1, const CFX_Matrix &m2)\r
-{\r
-    FX_FLOAT aa = m1.a * m2.a + m1.b * m2.c;\r
-    FX_FLOAT bb = m1.a * m2.b + m1.b * m2.d;\r
-    FX_FLOAT cc = m1.c * m2.a + m1.d * m2.c;\r
-    FX_FLOAT dd = m1.c * m2.b + m1.d * m2.d;\r
-    FX_FLOAT ee = m1.e * m2.a + m1.f * m2.c + m2.e;\r
-    FX_FLOAT ff = m1.e * m2.b + m1.f * m2.d + m2.f;\r
-    m.a = aa, m.b = bb, m.c = cc, m.d = dd, m.e = ee, m.f = ff;\r
-}\r
-void CFX_Matrix::Concat(FX_FLOAT a, FX_FLOAT b, FX_FLOAT c, FX_FLOAT d, FX_FLOAT e, FX_FLOAT f, FX_BOOL bPrepended)\r
-{\r
-    CFX_Matrix m;\r
-    m.Set(a, b, c, d, e, f);\r
-    Concat(m, bPrepended);\r
-}\r
-void CFX_Matrix::Concat(const CFX_Matrix &m, FX_BOOL bPrepended)\r
-{\r
-    if (bPrepended) {\r
-        FXCRT_Matrix_Concat(*this, m, *this);\r
-    } else {\r
-        FXCRT_Matrix_Concat(*this, *this, m);\r
-    }\r
-}\r
-void CFX_Matrix::ConcatInverse(const CFX_Matrix& src, FX_BOOL bPrepended)\r
-{\r
-    CFX_Matrix m;\r
-    m.SetReverse(src);\r
-    Concat(m, bPrepended);\r
-}\r
-FX_BOOL CFX_Matrix::IsInvertible() const\r
-{\r
-    return FXSYS_fabs(a * d - b * c) >= 0.0001f;\r
-}\r
-FX_BOOL CFX_Matrix::Is90Rotated() const\r
-{\r
-    return FXSYS_fabs(a * 1000) < FXSYS_fabs(b) && FXSYS_fabs(d * 1000) < FXSYS_fabs(c);\r
-}\r
-FX_BOOL CFX_Matrix::IsScaled() const\r
-{\r
-    return FXSYS_fabs(b * 1000) < FXSYS_fabs(a) && FXSYS_fabs(c * 1000) < FXSYS_fabs(d);\r
-}\r
-void CFX_Matrix::Translate(FX_FLOAT x, FX_FLOAT y, FX_BOOL bPrepended)\r
-{\r
-    if (bPrepended) {\r
-        e += x * a + y * c;\r
-        f += y * d + x * b;\r
-    } else {\r
-        e += x, f += y;\r
-    }\r
-}\r
-void CFX_Matrix::Scale(FX_FLOAT sx, FX_FLOAT sy, FX_BOOL bPrepended)\r
-{\r
-    a *= sx, d *= sy;\r
-    if (bPrepended) {\r
-        b *= sx;\r
-        c *= sy;\r
-    } else {\r
-        b *= sy;\r
-        c *= sx;\r
-        e *= sx;\r
-        f *= sy;\r
-    }\r
-}\r
-void CFX_Matrix::Rotate(FX_FLOAT fRadian, FX_BOOL bPrepended)\r
-{\r
-    FX_FLOAT cosValue = FXSYS_cos(fRadian);\r
-    FX_FLOAT sinValue = FXSYS_sin(fRadian);\r
-    CFX_Matrix m;\r
-    m.Set(cosValue, sinValue, -sinValue, cosValue, 0, 0);\r
-    if (bPrepended) {\r
-        FXCRT_Matrix_Concat(*this, m, *this);\r
-    } else {\r
-        FXCRT_Matrix_Concat(*this, *this, m);\r
-    }\r
-}\r
-void CFX_Matrix::RotateAt(FX_FLOAT fRadian, FX_FLOAT dx, FX_FLOAT dy, FX_BOOL bPrepended)\r
-{\r
-    Translate(dx, dy, bPrepended);\r
-    Rotate(fRadian, bPrepended);\r
-    Translate(-dx, -dy, bPrepended);\r
-}\r
-void CFX_Matrix::Shear(FX_FLOAT fAlphaRadian, FX_FLOAT fBetaRadian, FX_BOOL bPrepended)\r
-{\r
-    CFX_Matrix m;\r
-    m.Set(1, FXSYS_tan(fAlphaRadian), FXSYS_tan(fBetaRadian), 1, 0, 0);\r
-    if (bPrepended) {\r
-        FXCRT_Matrix_Concat(*this, m, *this);\r
-    } else {\r
-        FXCRT_Matrix_Concat(*this, *this, m);\r
-    }\r
-}\r
-void CFX_Matrix::MatchRect(const CFX_FloatRect& dest, const CFX_FloatRect& src)\r
-{\r
-    FX_FLOAT fDiff = src.left - src.right;\r
-    a = FXSYS_fabs(fDiff) < 0.001f ? 1 : (dest.left - dest.right) / fDiff;\r
-    fDiff = src.bottom - src.top;\r
-    d = FXSYS_fabs(fDiff) < 0.001f ? 1 : (dest.bottom - dest.top) / fDiff;\r
-    e = dest.left - src.left * a;\r
-    f = dest.bottom - src.bottom * d;\r
-    b = 0;\r
-    c = 0;\r
-}\r
-FX_FLOAT CFX_Matrix::GetXUnit() const\r
-{\r
-    if (b == 0) {\r
-        return (a > 0 ? a : -a);\r
-    }\r
-    if (a == 0) {\r
-        return (b > 0 ? b : -b);\r
-    }\r
-    return FXSYS_sqrt(a * a + b * b);\r
-}\r
-FX_FLOAT CFX_Matrix::GetYUnit() const\r
-{\r
-    if (c == 0) {\r
-        return (d > 0 ? d : -d);\r
-    }\r
-    if (d == 0) {\r
-        return (c > 0 ? c : -c);\r
-    }\r
-    return FXSYS_sqrt(c * c + d * d);\r
-}\r
-void CFX_Matrix::GetUnitRect(CFX_RectF &rect) const\r
-{\r
-    rect.left = rect.top = 0;\r
-    rect.width = rect.height = 1;\r
-    TransformRect(rect);\r
-}\r
-CFX_FloatRect CFX_Matrix::GetUnitRect() const\r
-{\r
-    CFX_FloatRect rect(0, 0, 1, 1);\r
-    rect.Transform((const CFX_Matrix*)this);\r
-    return rect;\r
-}\r
-FX_FLOAT CFX_Matrix::GetUnitArea() const\r
-{\r
-    FX_FLOAT A = FXSYS_sqrt(a * a + b * b);\r
-    FX_FLOAT B = FXSYS_sqrt(c * c + d * d);\r
-    FX_FLOAT ac = a + c, bd = b + d;\r
-    FX_FLOAT C = FXSYS_sqrt(ac * ac + bd * bd);\r
-    FX_FLOAT P = (A + B + C ) / 2;\r
-    return FXSYS_sqrt(P * (P - A) * (P - B) * (P - C)) * 2;\r
-}\r
-FX_FLOAT CFX_Matrix::TransformXDistance(FX_FLOAT dx) const\r
-{\r
-    FX_FLOAT fx = a * dx, fy = b * dx;\r
-    return FXSYS_sqrt(fx * fx + fy * fy);\r
-}\r
-FX_INT32 CFX_Matrix::TransformXDistance(FX_INT32 dx) const\r
-{\r
-    FX_FLOAT fx = a * dx, fy = b * dx;\r
-    return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));\r
-}\r
-FX_FLOAT CFX_Matrix::TransformYDistance(FX_FLOAT dy) const\r
-{\r
-    FX_FLOAT fx = c * dy, fy = d * dy;\r
-    return FXSYS_sqrt(fx * fx + fy * fy);\r
-}\r
-FX_INT32 CFX_Matrix::TransformYDistance(FX_INT32 dy) const\r
-{\r
-    FX_FLOAT fx = c * dy, fy = d * dy;\r
-    return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));\r
-}\r
-FX_FLOAT CFX_Matrix::TransformDistance(FX_FLOAT dx, FX_FLOAT dy) const\r
-{\r
-    FX_FLOAT fx = a * dx + c * dy, fy = b * dx + d * dy;\r
-    return FXSYS_sqrt(fx * fx + fy * fy);\r
-}\r
-FX_INT32 CFX_Matrix::TransformDistance(FX_INT32 dx, FX_INT32 dy) const\r
-{\r
-    FX_FLOAT fx = a * dx + c * dy, fy = b * dx + d * dy;\r
-    return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));\r
-}\r
-FX_FLOAT CFX_Matrix::TransformDistance(FX_FLOAT distance) const\r
-{\r
-    return distance * (GetXUnit() + GetYUnit()) / 2;\r
-}\r
-void CFX_Matrix::TransformVector(CFX_VectorF &v) const\r
-{\r
-    FX_FLOAT fx = a * v.x + c * v.y;\r
-    FX_FLOAT fy = b * v.x + d * v.y;\r
-    v.x = fx, v.y = fy;\r
-}\r
-void CFX_Matrix::TransformVector(CFX_Vector &v) const\r
-{\r
-    FX_FLOAT fx = a * v.x + c * v.y;\r
-    FX_FLOAT fy = b * v.x + d * v.y;\r
-    v.x = FXSYS_round(fx);\r
-    v.y = FXSYS_round(fy);\r
-}\r
-void CFX_Matrix::TransformPoints(CFX_Point *points, FX_INT32 iCount) const\r
-{\r
-    FXSYS_assert(iCount > 0);\r
-    FX_FLOAT fx, fy;\r
-    for (FX_INT32 i = 0; i < iCount; i ++) {\r
-        fx = a * points->x + c * points->y + e;\r
-        fy = b * points->x + d * points->y + f;\r
-        points->x = FXSYS_round(fx);\r
-        points->y = FXSYS_round(fy);\r
-        points ++;\r
-    }\r
-}\r
-void CFX_Matrix::TransformPoints(CFX_PointF *points, FX_INT32 iCount) const\r
-{\r
-    FXSYS_assert(iCount > 0);\r
-    FX_FLOAT fx, fy;\r
-    for (FX_INT32 i = 0; i < iCount; i ++) {\r
-        fx = a * points->x + c * points->y + e;\r
-        fy = b * points->x + d * points->y + f;\r
-        points->x = fx, points->y = fy;\r
-        points ++;\r
-    }\r
-}\r
-void CFX_Matrix::TransformPoint(FX_FLOAT &x, FX_FLOAT &y) const\r
-{\r
-    FX_FLOAT fx = a * x + c * y + e;\r
-    FX_FLOAT fy = b * x + d * y + f;\r
-    x = fx, y = fy;\r
-}\r
-void CFX_Matrix::TransformPoint(FX_INT32 &x, FX_INT32 &y) const\r
-{\r
-    FX_FLOAT fx = a * x + c * y + e;\r
-    FX_FLOAT fy = b * x + d * y + f;\r
-    x = FXSYS_round(fx);\r
-    y = FXSYS_round(fy);\r
-}\r
-void CFX_Matrix::TransformRect(CFX_RectF &rect) const\r
-{\r
-    FX_FLOAT right = rect.right(), bottom = rect.bottom();\r
-    TransformRect(rect.left, right, bottom, rect.top);\r
-    rect.width = right - rect.left;\r
-    rect.height = bottom - rect.top;\r
-}\r
-void CFX_Matrix::TransformRect(CFX_Rect &rect) const\r
-{\r
-    FX_FLOAT left = (FX_FLOAT)rect.left;\r
-    FX_FLOAT top = (FX_FLOAT)rect.bottom();\r
-    FX_FLOAT right = (FX_FLOAT)rect.right();\r
-    FX_FLOAT bottom = (FX_FLOAT)rect.top;\r
-    TransformRect(left, right, top, bottom);\r
-    rect.left = FXSYS_round(left);\r
-    rect.top = FXSYS_round(bottom);\r
-    rect.width = FXSYS_round(right - left);\r
-    rect.height = FXSYS_round(top - bottom);\r
-}\r
-void CFX_Matrix::TransformRect(FX_FLOAT& left, FX_FLOAT& right, FX_FLOAT& top, FX_FLOAT& bottom) const\r
-{\r
-    FX_FLOAT x[4], y[4];\r
-    x[0] = left;\r
-    y[0] = top;\r
-    x[1] = left;\r
-    y[1] = bottom;\r
-    x[2] = right;\r
-    y[2] = top;\r
-    x[3] = right;\r
-    y[3] = bottom;\r
-    int i;\r
-    for (i = 0; i < 4; i ++) {\r
-        Transform(x[i], y[i], x[i], y[i]);\r
-    }\r
-    right = left = x[0];\r
-    top = bottom = y[0];\r
-    for (i = 1; i < 4; i ++) {\r
-        if (right < x[i]) {\r
-            right = x[i];\r
-        }\r
-        if (left > x[i]) {\r
-            left = x[i];\r
-        }\r
-        if (top < y[i]) {\r
-            top = y[i];\r
-        }\r
-        if (bottom > y[i]) {\r
-            bottom = y[i];\r
-        }\r
-    }\r
-}\r
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include <limits.h>
+#include "../../include/fxcrt/fx_ext.h"
+void FX_RECT::Normalize()
+{
+    if (left > right) {
+        int temp = left;
+        left = right;
+        right = temp;
+    }
+    if (top > bottom) {
+        int temp = top;
+        top = bottom;
+        bottom = temp;
+    }
+}
+void FX_RECT::Intersect(const FX_RECT& src)
+{
+    FX_RECT src_n = src;
+    src_n.Normalize();
+    Normalize();
+    left = left > src_n.left ? left : src_n.left;
+    top = top > src_n.top ? top : src_n.top;
+    right = right < src_n.right ? right : src_n.right;
+    bottom = bottom < src_n.bottom ? bottom : src_n.bottom;
+    if (left > right || top > bottom) {
+        left = top = right = bottom = 0;
+    }
+}
+void FX_RECT::Union(const FX_RECT& other_rect)
+{
+    Normalize();
+    FX_RECT other = other_rect;
+    other.Normalize();
+    left = left < other.left ? left : other.left;
+    right = right > other.right ? right : other.right;
+    bottom = bottom > other.bottom ? bottom : other.bottom;
+    top = top < other.top ? top : other.top;
+}
+FX_BOOL GetIntersection(FX_FLOAT low1, FX_FLOAT high1, FX_FLOAT low2, FX_FLOAT high2,
+                        FX_FLOAT& interlow, FX_FLOAT& interhigh)
+{
+    if (low1 >= high2 || low2 >= high1) {
+        return FALSE;
+    }
+    interlow = low1 > low2 ? low1 : low2;
+    interhigh = high1 > high2 ? high2 : high1;
+    return TRUE;
+}
+extern "C" int FXSYS_round(FX_FLOAT d)
+{
+    if (d < (FX_FLOAT)INT_MIN) {
+        return INT_MIN;
+    }
+    if (d > (FX_FLOAT)INT_MAX) {
+        return INT_MAX;
+    }
+
+    return (int)round(d);
+}
+CFX_FloatRect::CFX_FloatRect(const FX_RECT& rect)
+{
+    left = (FX_FLOAT)(rect.left);
+    right = (FX_FLOAT)(rect.right);
+    bottom = (FX_FLOAT)(rect.top);
+    top = (FX_FLOAT)(rect.bottom);
+}
+void CFX_FloatRect::Normalize()
+{
+    FX_FLOAT temp;
+    if (left > right) {
+        temp = left;
+        left = right;
+        right = temp;
+    }
+    if (bottom > top) {
+        temp = top;
+        top = bottom;
+        bottom = temp;
+    }
+}
+void CFX_FloatRect::Intersect(const CFX_FloatRect& other_rect)
+{
+    Normalize();
+    CFX_FloatRect other = other_rect;
+    other.Normalize();
+    left = left > other.left ? left : other.left;
+    right = right < other.right ? right : other.right;
+    bottom = bottom > other.bottom ? bottom : other.bottom;
+    top = top < other.top ? top : other.top;
+    if (left > right || bottom > top) {
+        left = right = bottom = top = 0;
+    }
+}
+void CFX_FloatRect::Union(const CFX_FloatRect& other_rect)
+{
+    Normalize();
+    CFX_FloatRect other = other_rect;
+    other.Normalize();
+    left = left < other.left ? left : other.left;
+    right = right > other.right ? right : other.right;
+    bottom = bottom < other.bottom ? bottom : other.bottom;
+    top = top > other.top ? top : other.top;
+}
+void CFX_FloatRect::Transform(const CFX_Matrix* pMatrix)
+{
+    pMatrix->TransformRect(left, right, top, bottom);
+}
+int CFX_FloatRect::Substract4(CFX_FloatRect& s, CFX_FloatRect* pRects)
+{
+    Normalize();
+    s.Normalize();
+    int nRects = 0;
+    CFX_FloatRect rects[4];
+    if (left < s.left) {
+        rects[nRects].left = left;
+        rects[nRects].right = s.left;
+        rects[nRects].bottom = bottom;
+        rects[nRects].top = top;
+        nRects ++;
+    }
+    if (s.left < right && s.top < top) {
+        rects[nRects].left = s.left;
+        rects[nRects].right = right;
+        rects[nRects].bottom = s.top;
+        rects[nRects].top = top;
+        nRects ++;
+    }
+    if (s.top > bottom && s.right < right) {
+        rects[nRects].left = s.right;
+        rects[nRects].right = right;
+        rects[nRects].bottom = bottom;
+        rects[nRects].top = s.top;
+        nRects ++;
+    }
+    if (s.bottom > bottom) {
+        rects[nRects].left = s.left;
+        rects[nRects].right = s.right;
+        rects[nRects].bottom = bottom;
+        rects[nRects].top = s.bottom;
+        nRects ++;
+    }
+    if (nRects == 0) {
+        return 0;
+    }
+    for (int i = 0; i < nRects; i ++) {
+        pRects[i] = rects[i];
+        pRects[i].Intersect(*this);
+    }
+    return nRects;
+}
+FX_RECT CFX_FloatRect::GetOutterRect() const
+{
+    CFX_FloatRect rect1 = *this;
+    FX_RECT rect;
+    rect.left = (int)FXSYS_floor(rect1.left);
+    rect.right = (int)FXSYS_ceil(rect1.right);
+    rect.top = (int)FXSYS_floor(rect1.bottom);
+    rect.bottom = (int)FXSYS_ceil(rect1.top);
+    rect.Normalize();
+    return rect;
+}
+FX_RECT CFX_FloatRect::GetInnerRect() const
+{
+    CFX_FloatRect rect1 = *this;
+    FX_RECT rect;
+    rect.left = (int)FXSYS_ceil(rect1.left);
+    rect.right = (int)FXSYS_floor(rect1.right);
+    rect.top = (int)FXSYS_ceil(rect1.bottom);
+    rect.bottom = (int)FXSYS_floor(rect1.top);
+    rect.Normalize();
+    return rect;
+}
+static void _MatchFloatRange(FX_FLOAT f1, FX_FLOAT f2, int& i1, int& i2)
+{
+    int length = (int)FXSYS_ceil(f2 - f1);
+    int i1_1 = (int)FXSYS_floor(f1);
+    int i1_2 = (int)FXSYS_ceil(f1);
+    FX_FLOAT error1 = f1 - i1_1 + (FX_FLOAT)FXSYS_fabs(f2 - i1_1 - length);
+    FX_FLOAT error2 = i1_2 - f1 + (FX_FLOAT)FXSYS_fabs(f2 - i1_2 - length);
+    i1 = (error1 > error2) ? i1_2 : i1_1;
+    i2 = i1 + length;
+}
+FX_RECT CFX_FloatRect::GetClosestRect() const
+{
+    CFX_FloatRect rect1 = *this;
+    FX_RECT rect;
+    _MatchFloatRange(rect1.left, rect1.right, rect.left, rect.right);
+    _MatchFloatRange(rect1.bottom, rect1.top, rect.top, rect.bottom);
+    rect.Normalize();
+    return rect;
+}
+FX_BOOL CFX_FloatRect::Contains(const CFX_FloatRect& other_rect) const
+{
+    CFX_FloatRect n1 = *this;
+    n1.Normalize();
+    CFX_FloatRect n2 = other_rect;
+    n2.Normalize();
+    if (n2.left >= n1.left && n2.right <= n1.right && n2.bottom >= n1.bottom && n2.top <= n1.top) {
+        return TRUE;
+    }
+    return FALSE;
+}
+FX_BOOL CFX_FloatRect::Contains(FX_FLOAT x, FX_FLOAT y) const
+{
+    CFX_FloatRect n1 = *this;
+    n1.Normalize();
+    return x <= n1.right && x >= n1.left && y <= n1.top && y >= n1.bottom;
+}
+void CFX_FloatRect::UpdateRect(FX_FLOAT x, FX_FLOAT y)
+{
+    if (left > x) {
+        left = x;
+    }
+    if (right < x) {
+        right = x;
+    }
+    if (bottom > y) {
+        bottom = y;
+    }
+    if (top < y) {
+        top = y;
+    }
+}
+CFX_FloatRect CFX_FloatRect::GetBBox(const CFX_FloatPoint* pPoints, int nPoints)
+{
+    if (nPoints == 0) {
+        return CFX_FloatRect();
+    }
+    FX_FLOAT min_x = pPoints->x, max_x = pPoints->x, min_y = pPoints->y, max_y = pPoints->y;
+    for (int i = 1; i < nPoints; i ++) {
+        if (min_x > pPoints[i].x) {
+            min_x = pPoints[i].x;
+        }
+        if (max_x < pPoints[i].x) {
+            max_x = pPoints[i].x;
+        }
+        if (min_y > pPoints[i].y) {
+            min_y = pPoints[i].y;
+        }
+        if (max_y < pPoints[i].y) {
+            max_y = pPoints[i].y;
+        }
+    }
+    return CFX_FloatRect(min_x, min_y, max_x, max_y);
+}
+void CFX_Matrix::Set(FX_FLOAT a, FX_FLOAT b, FX_FLOAT c, FX_FLOAT d, FX_FLOAT e, FX_FLOAT f)
+{
+    this->a = a;
+    this->b = b;
+    this->c = c;
+    this->d = d;
+    this->e = e;
+    this->f = f;
+}
+void CFX_Matrix::Set(const FX_FLOAT n[6])
+{
+    this->a = n[0];
+    this->b = n[1];
+    this->c = n[2];
+    this->d = n[3];
+    this->e = n[4];
+    this->f = n[5];
+}
+void CFX_Matrix::SetReverse(const CFX_Matrix &m)
+{
+    FX_FLOAT i = m.a * m.d - m.b * m.c;
+    if (FXSYS_fabs(i) == 0) {
+        return;
+    }
+    FX_FLOAT j = -i;
+    a = m.d / i;
+    b = m.b / j;
+    c = m.c / j;
+    d = m.a / i;
+    e = (m.c * m.f - m.d * m.e) / i;
+    f = (m.a * m.f - m.b * m.e) / j;
+}
+static void FXCRT_Matrix_Concat(CFX_Matrix &m, const CFX_Matrix &m1, const CFX_Matrix &m2)
+{
+    FX_FLOAT aa = m1.a * m2.a + m1.b * m2.c;
+    FX_FLOAT bb = m1.a * m2.b + m1.b * m2.d;
+    FX_FLOAT cc = m1.c * m2.a + m1.d * m2.c;
+    FX_FLOAT dd = m1.c * m2.b + m1.d * m2.d;
+    FX_FLOAT ee = m1.e * m2.a + m1.f * m2.c + m2.e;
+    FX_FLOAT ff = m1.e * m2.b + m1.f * m2.d + m2.f;
+    m.a = aa, m.b = bb, m.c = cc, m.d = dd, m.e = ee, m.f = ff;
+}
+void CFX_Matrix::Concat(FX_FLOAT a, FX_FLOAT b, FX_FLOAT c, FX_FLOAT d, FX_FLOAT e, FX_FLOAT f, FX_BOOL bPrepended)
+{
+    CFX_Matrix m;
+    m.Set(a, b, c, d, e, f);
+    Concat(m, bPrepended);
+}
+void CFX_Matrix::Concat(const CFX_Matrix &m, FX_BOOL bPrepended)
+{
+    if (bPrepended) {
+        FXCRT_Matrix_Concat(*this, m, *this);
+    } else {
+        FXCRT_Matrix_Concat(*this, *this, m);
+    }
+}
+void CFX_Matrix::ConcatInverse(const CFX_Matrix& src, FX_BOOL bPrepended)
+{
+    CFX_Matrix m;
+    m.SetReverse(src);
+    Concat(m, bPrepended);
+}
+FX_BOOL CFX_Matrix::IsInvertible() const
+{
+    return FXSYS_fabs(a * d - b * c) >= 0.0001f;
+}
+FX_BOOL CFX_Matrix::Is90Rotated() const
+{
+    return FXSYS_fabs(a * 1000) < FXSYS_fabs(b) && FXSYS_fabs(d * 1000) < FXSYS_fabs(c);
+}
+FX_BOOL CFX_Matrix::IsScaled() const
+{
+    return FXSYS_fabs(b * 1000) < FXSYS_fabs(a) && FXSYS_fabs(c * 1000) < FXSYS_fabs(d);
+}
+void CFX_Matrix::Translate(FX_FLOAT x, FX_FLOAT y, FX_BOOL bPrepended)
+{
+    if (bPrepended) {
+        e += x * a + y * c;
+        f += y * d + x * b;
+    } else {
+        e += x, f += y;
+    }
+}
+void CFX_Matrix::Scale(FX_FLOAT sx, FX_FLOAT sy, FX_BOOL bPrepended)
+{
+    a *= sx, d *= sy;
+    if (bPrepended) {
+        b *= sx;
+        c *= sy;
+    } else {
+        b *= sy;
+        c *= sx;
+        e *= sx;
+        f *= sy;
+    }
+}
+void CFX_Matrix::Rotate(FX_FLOAT fRadian, FX_BOOL bPrepended)
+{
+    FX_FLOAT cosValue = FXSYS_cos(fRadian);
+    FX_FLOAT sinValue = FXSYS_sin(fRadian);
+    CFX_Matrix m;
+    m.Set(cosValue, sinValue, -sinValue, cosValue, 0, 0);
+    if (bPrepended) {
+        FXCRT_Matrix_Concat(*this, m, *this);
+    } else {
+        FXCRT_Matrix_Concat(*this, *this, m);
+    }
+}
+void CFX_Matrix::RotateAt(FX_FLOAT fRadian, FX_FLOAT dx, FX_FLOAT dy, FX_BOOL bPrepended)
+{
+    Translate(dx, dy, bPrepended);
+    Rotate(fRadian, bPrepended);
+    Translate(-dx, -dy, bPrepended);
+}
+void CFX_Matrix::Shear(FX_FLOAT fAlphaRadian, FX_FLOAT fBetaRadian, FX_BOOL bPrepended)
+{
+    CFX_Matrix m;
+    m.Set(1, FXSYS_tan(fAlphaRadian), FXSYS_tan(fBetaRadian), 1, 0, 0);
+    if (bPrepended) {
+        FXCRT_Matrix_Concat(*this, m, *this);
+    } else {
+        FXCRT_Matrix_Concat(*this, *this, m);
+    }
+}
+void CFX_Matrix::MatchRect(const CFX_FloatRect& dest, const CFX_FloatRect& src)
+{
+    FX_FLOAT fDiff = src.left - src.right;
+    a = FXSYS_fabs(fDiff) < 0.001f ? 1 : (dest.left - dest.right) / fDiff;
+    fDiff = src.bottom - src.top;
+    d = FXSYS_fabs(fDiff) < 0.001f ? 1 : (dest.bottom - dest.top) / fDiff;
+    e = dest.left - src.left * a;
+    f = dest.bottom - src.bottom * d;
+    b = 0;
+    c = 0;
+}
+FX_FLOAT CFX_Matrix::GetXUnit() const
+{
+    if (b == 0) {
+        return (a > 0 ? a : -a);
+    }
+    if (a == 0) {
+        return (b > 0 ? b : -b);
+    }
+    return FXSYS_sqrt(a * a + b * b);
+}
+FX_FLOAT CFX_Matrix::GetYUnit() const
+{
+    if (c == 0) {
+        return (d > 0 ? d : -d);
+    }
+    if (d == 0) {
+        return (c > 0 ? c : -c);
+    }
+    return FXSYS_sqrt(c * c + d * d);
+}
+void CFX_Matrix::GetUnitRect(CFX_RectF &rect) const
+{
+    rect.left = rect.top = 0;
+    rect.width = rect.height = 1;
+    TransformRect(rect);
+}
+CFX_FloatRect CFX_Matrix::GetUnitRect() const
+{
+    CFX_FloatRect rect(0, 0, 1, 1);
+    rect.Transform((const CFX_Matrix*)this);
+    return rect;
+}
+FX_FLOAT CFX_Matrix::GetUnitArea() const
+{
+    FX_FLOAT A = FXSYS_sqrt(a * a + b * b);
+    FX_FLOAT B = FXSYS_sqrt(c * c + d * d);
+    FX_FLOAT ac = a + c, bd = b + d;
+    FX_FLOAT C = FXSYS_sqrt(ac * ac + bd * bd);
+    FX_FLOAT P = (A + B + C ) / 2;
+    return FXSYS_sqrt(P * (P - A) * (P - B) * (P - C)) * 2;
+}
+FX_FLOAT CFX_Matrix::TransformXDistance(FX_FLOAT dx) const
+{
+    FX_FLOAT fx = a * dx, fy = b * dx;
+    return FXSYS_sqrt(fx * fx + fy * fy);
+}
+FX_INT32 CFX_Matrix::TransformXDistance(FX_INT32 dx) const
+{
+    FX_FLOAT fx = a * dx, fy = b * dx;
+    return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));
+}
+FX_FLOAT CFX_Matrix::TransformYDistance(FX_FLOAT dy) const
+{
+    FX_FLOAT fx = c * dy, fy = d * dy;
+    return FXSYS_sqrt(fx * fx + fy * fy);
+}
+FX_INT32 CFX_Matrix::TransformYDistance(FX_INT32 dy) const
+{
+    FX_FLOAT fx = c * dy, fy = d * dy;
+    return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));
+}
+FX_FLOAT CFX_Matrix::TransformDistance(FX_FLOAT dx, FX_FLOAT dy) const
+{
+    FX_FLOAT fx = a * dx + c * dy, fy = b * dx + d * dy;
+    return FXSYS_sqrt(fx * fx + fy * fy);
+}
+FX_INT32 CFX_Matrix::TransformDistance(FX_INT32 dx, FX_INT32 dy) const
+{
+    FX_FLOAT fx = a * dx + c * dy, fy = b * dx + d * dy;
+    return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));
+}
+FX_FLOAT CFX_Matrix::TransformDistance(FX_FLOAT distance) const
+{
+    return distance * (GetXUnit() + GetYUnit()) / 2;
+}
+void CFX_Matrix::TransformVector(CFX_VectorF &v) const
+{
+    FX_FLOAT fx = a * v.x + c * v.y;
+    FX_FLOAT fy = b * v.x + d * v.y;
+    v.x = fx, v.y = fy;
+}
+void CFX_Matrix::TransformVector(CFX_Vector &v) const
+{
+    FX_FLOAT fx = a * v.x + c * v.y;
+    FX_FLOAT fy = b * v.x + d * v.y;
+    v.x = FXSYS_round(fx);
+    v.y = FXSYS_round(fy);
+}
+void CFX_Matrix::TransformPoints(CFX_Point *points, FX_INT32 iCount) const
+{
+    FXSYS_assert(iCount > 0);
+    FX_FLOAT fx, fy;
+    for (FX_INT32 i = 0; i < iCount; i ++) {
+        fx = a * points->x + c * points->y + e;
+        fy = b * points->x + d * points->y + f;
+        points->x = FXSYS_round(fx);
+        points->y = FXSYS_round(fy);
+        points ++;
+    }
+}
+void CFX_Matrix::TransformPoints(CFX_PointF *points, FX_INT32 iCount) const
+{
+    FXSYS_assert(iCount > 0);
+    FX_FLOAT fx, fy;
+    for (FX_INT32 i = 0; i < iCount; i ++) {
+        fx = a * points->x + c * points->y + e;
+        fy = b * points->x + d * points->y + f;
+        points->x = fx, points->y = fy;
+        points ++;
+    }
+}
+void CFX_Matrix::TransformPoint(FX_FLOAT &x, FX_FLOAT &y) const
+{
+    FX_FLOAT fx = a * x + c * y + e;
+    FX_FLOAT fy = b * x + d * y + f;
+    x = fx, y = fy;
+}
+void CFX_Matrix::TransformPoint(FX_INT32 &x, FX_INT32 &y) const
+{
+    FX_FLOAT fx = a * x + c * y + e;
+    FX_FLOAT fy = b * x + d * y + f;
+    x = FXSYS_round(fx);
+    y = FXSYS_round(fy);
+}
+void CFX_Matrix::TransformRect(CFX_RectF &rect) const
+{
+    FX_FLOAT right = rect.right(), bottom = rect.bottom();
+    TransformRect(rect.left, right, bottom, rect.top);
+    rect.width = right - rect.left;
+    rect.height = bottom - rect.top;
+}
+void CFX_Matrix::TransformRect(CFX_Rect &rect) const
+{
+    FX_FLOAT left = (FX_FLOAT)rect.left;
+    FX_FLOAT top = (FX_FLOAT)rect.bottom();
+    FX_FLOAT right = (FX_FLOAT)rect.right();
+    FX_FLOAT bottom = (FX_FLOAT)rect.top;
+    TransformRect(left, right, top, bottom);
+    rect.left = FXSYS_round(left);
+    rect.top = FXSYS_round(bottom);
+    rect.width = FXSYS_round(right - left);
+    rect.height = FXSYS_round(top - bottom);
+}
+void CFX_Matrix::TransformRect(FX_FLOAT& left, FX_FLOAT& right, FX_FLOAT& top, FX_FLOAT& bottom) const
+{
+    FX_FLOAT x[4], y[4];
+    x[0] = left;
+    y[0] = top;
+    x[1] = left;
+    y[1] = bottom;
+    x[2] = right;
+    y[2] = top;
+    x[3] = right;
+    y[3] = bottom;
+    int i;
+    for (i = 0; i < 4; i ++) {
+        Transform(x[i], y[i], x[i], y[i]);
+    }
+    right = left = x[0];
+    top = bottom = y[0];
+    for (i = 1; i < 4; i ++) {
+        if (right < x[i]) {
+            right = x[i];
+        }
+        if (left > x[i]) {
+            left = x[i];
+        }
+        if (top < y[i]) {
+            top = y[i];
+        }
+        if (bottom > y[i]) {
+            bottom = y[i];
+        }
+    }
+}