Home | History | Annotate | Download | only in fxcrt
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "../../include/fxcrt/fx_ext.h"
      8 void FX_RECT::Normalize()
      9 {
     10     if (left > right) {
     11         int temp = left;
     12         left = right;
     13         right = temp;
     14     }
     15     if (top > bottom) {
     16         int temp = top;
     17         top = bottom;
     18         bottom = temp;
     19     }
     20 }
     21 void FX_RECT::Intersect(const FX_RECT& src)
     22 {
     23     FX_RECT src_n = src;
     24     src_n.Normalize();
     25     Normalize();
     26     left = left > src_n.left ? left : src_n.left;
     27     top = top > src_n.top ? top : src_n.top;
     28     right = right < src_n.right ? right : src_n.right;
     29     bottom = bottom < src_n.bottom ? bottom : src_n.bottom;
     30     if (left > right || top > bottom) {
     31         left = top = right = bottom = 0;
     32     }
     33 }
     34 void FX_RECT::Union(const FX_RECT& other_rect)
     35 {
     36     Normalize();
     37     FX_RECT other = other_rect;
     38     other.Normalize();
     39     left = left < other.left ? left : other.left;
     40     right = right > other.right ? right : other.right;
     41     bottom = bottom > other.bottom ? bottom : other.bottom;
     42     top = top < other.top ? top : other.top;
     43 }
     44 FX_BOOL GetIntersection(FX_FLOAT low1, FX_FLOAT high1, FX_FLOAT low2, FX_FLOAT high2,
     45                         FX_FLOAT& interlow, FX_FLOAT& interhigh)
     46 {
     47     if (low1 >= high2 || low2 >= high1) {
     48         return FALSE;
     49     }
     50     interlow = low1 > low2 ? low1 : low2;
     51     interhigh = high1 > high2 ? high2 : high1;
     52     return TRUE;
     53 }
     54 extern "C" int FXSYS_round(FX_FLOAT d)
     55 {
     56     int iRet = 0;
     57     if (d >= 0.0f) {
     58         iRet = (int)(d + 0.5f);
     59         if (iRet >= 0) {
     60             return iRet;
     61         }
     62         return -iRet;
     63     }
     64     return (int)(d - 0.5f);
     65 }
     66 CFX_FloatRect::CFX_FloatRect(const FX_RECT& rect)
     67 {
     68     left = (FX_FLOAT)(rect.left);
     69     right = (FX_FLOAT)(rect.right);
     70     bottom = (FX_FLOAT)(rect.top);
     71     top = (FX_FLOAT)(rect.bottom);
     72 }
     73 void CFX_FloatRect::Normalize()
     74 {
     75     FX_FLOAT temp;
     76     if (left > right) {
     77         temp = left;
     78         left = right;
     79         right = temp;
     80     }
     81     if (bottom > top) {
     82         temp = top;
     83         top = bottom;
     84         bottom = temp;
     85     }
     86 }
     87 void CFX_FloatRect::Intersect(const CFX_FloatRect& other_rect)
     88 {
     89     Normalize();
     90     CFX_FloatRect other = other_rect;
     91     other.Normalize();
     92     left = left > other.left ? left : other.left;
     93     right = right < other.right ? right : other.right;
     94     bottom = bottom > other.bottom ? bottom : other.bottom;
     95     top = top < other.top ? top : other.top;
     96     if (left > right || bottom > top) {
     97         left = right = bottom = top = 0;
     98     }
     99 }
    100 void CFX_FloatRect::Union(const CFX_FloatRect& other_rect)
    101 {
    102     Normalize();
    103     CFX_FloatRect other = other_rect;
    104     other.Normalize();
    105     left = left < other.left ? left : other.left;
    106     right = right > other.right ? right : other.right;
    107     bottom = bottom < other.bottom ? bottom : other.bottom;
    108     top = top > other.top ? top : other.top;
    109 }
    110 void CFX_FloatRect::Transform(const CFX_Matrix* pMatrix)
    111 {
    112     pMatrix->TransformRect(left, right, top, bottom);
    113 }
    114 int CFX_FloatRect::Substract4(CFX_FloatRect& s, CFX_FloatRect* pRects)
    115 {
    116     Normalize();
    117     s.Normalize();
    118     int nRects = 0;
    119     CFX_FloatRect rects[4];
    120     if (left < s.left) {
    121         rects[nRects].left = left;
    122         rects[nRects].right = s.left;
    123         rects[nRects].bottom = bottom;
    124         rects[nRects].top = top;
    125         nRects ++;
    126     }
    127     if (s.left < right && s.top < top) {
    128         rects[nRects].left = s.left;
    129         rects[nRects].right = right;
    130         rects[nRects].bottom = s.top;
    131         rects[nRects].top = top;
    132         nRects ++;
    133     }
    134     if (s.top > bottom && s.right < right) {
    135         rects[nRects].left = s.right;
    136         rects[nRects].right = right;
    137         rects[nRects].bottom = bottom;
    138         rects[nRects].top = s.top;
    139         nRects ++;
    140     }
    141     if (s.bottom > bottom) {
    142         rects[nRects].left = s.left;
    143         rects[nRects].right = s.right;
    144         rects[nRects].bottom = bottom;
    145         rects[nRects].top = s.bottom;
    146         nRects ++;
    147     }
    148     if (nRects == 0) {
    149         return 0;
    150     }
    151     for (int i = 0; i < nRects; i ++) {
    152         pRects[i] = rects[i];
    153         pRects[i].Intersect(*this);
    154     }
    155     return nRects;
    156 }
    157 FX_RECT CFX_FloatRect::GetOutterRect() const
    158 {
    159     CFX_FloatRect rect1 = *this;
    160     FX_RECT rect;
    161     rect.left = (int)FXSYS_floor(rect1.left);
    162     rect.right = (int)FXSYS_ceil(rect1.right);
    163     rect.top = (int)FXSYS_floor(rect1.bottom);
    164     rect.bottom = (int)FXSYS_ceil(rect1.top);
    165     rect.Normalize();
    166     return rect;
    167 }
    168 FX_RECT CFX_FloatRect::GetInnerRect() const
    169 {
    170     CFX_FloatRect rect1 = *this;
    171     FX_RECT rect;
    172     rect.left = (int)FXSYS_ceil(rect1.left);
    173     rect.right = (int)FXSYS_floor(rect1.right);
    174     rect.top = (int)FXSYS_ceil(rect1.bottom);
    175     rect.bottom = (int)FXSYS_floor(rect1.top);
    176     rect.Normalize();
    177     return rect;
    178 }
    179 static void _MatchFloatRange(FX_FLOAT f1, FX_FLOAT f2, int& i1, int& i2)
    180 {
    181     int length = (int)FXSYS_ceil(f2 - f1);
    182     int i1_1 = (int)FXSYS_floor(f1);
    183     int i1_2 = (int)FXSYS_ceil(f1);
    184     FX_FLOAT error1 = f1 - i1_1 + (FX_FLOAT)FXSYS_fabs(f2 - i1_1 - length);
    185     FX_FLOAT error2 = i1_2 - f1 + (FX_FLOAT)FXSYS_fabs(f2 - i1_2 - length);
    186     i1 = (error1 > error2) ? i1_2 : i1_1;
    187     i2 = i1 + length;
    188 }
    189 FX_RECT CFX_FloatRect::GetClosestRect() const
    190 {
    191     CFX_FloatRect rect1 = *this;
    192     FX_RECT rect;
    193     _MatchFloatRange(rect1.left, rect1.right, rect.left, rect.right);
    194     _MatchFloatRange(rect1.bottom, rect1.top, rect.top, rect.bottom);
    195     rect.Normalize();
    196     return rect;
    197 }
    198 FX_BOOL CFX_FloatRect::Contains(const CFX_FloatRect& other_rect) const
    199 {
    200     CFX_FloatRect n1 = *this;
    201     n1.Normalize();
    202     CFX_FloatRect n2 = other_rect;
    203     n2.Normalize();
    204     if (n2.left >= n1.left && n2.right <= n1.right && n2.bottom >= n1.bottom && n2.top <= n1.top) {
    205         return TRUE;
    206     }
    207     return FALSE;
    208 }
    209 FX_BOOL CFX_FloatRect::Contains(FX_FLOAT x, FX_FLOAT y) const
    210 {
    211     CFX_FloatRect n1 = *this;
    212     n1.Normalize();
    213     return x <= n1.right && x >= n1.left && y <= n1.top && y >= n1.bottom;
    214 }
    215 void CFX_FloatRect::UpdateRect(FX_FLOAT x, FX_FLOAT y)
    216 {
    217     if (left > x) {
    218         left = x;
    219     }
    220     if (right < x) {
    221         right = x;
    222     }
    223     if (bottom > y) {
    224         bottom = y;
    225     }
    226     if (top < y) {
    227         top = y;
    228     }
    229 }
    230 CFX_FloatRect CFX_FloatRect::GetBBox(const CFX_FloatPoint* pPoints, int nPoints)
    231 {
    232     if (nPoints == 0) {
    233         return CFX_FloatRect();
    234     }
    235     FX_FLOAT min_x = pPoints->x, max_x = pPoints->x, min_y = pPoints->y, max_y = pPoints->y;
    236     for (int i = 1; i < nPoints; i ++) {
    237         if (min_x > pPoints[i].x) {
    238             min_x = pPoints[i].x;
    239         }
    240         if (max_x < pPoints[i].x) {
    241             max_x = pPoints[i].x;
    242         }
    243         if (min_y > pPoints[i].y) {
    244             min_y = pPoints[i].y;
    245         }
    246         if (max_y < pPoints[i].y) {
    247             max_y = pPoints[i].y;
    248         }
    249     }
    250     return CFX_FloatRect(min_x, min_y, max_x, max_y);
    251 }
    252 void CFX_Matrix::Set(FX_FLOAT a, FX_FLOAT b, FX_FLOAT c, FX_FLOAT d, FX_FLOAT e, FX_FLOAT f)
    253 {
    254     this->a = a;
    255     this->b = b;
    256     this->c = c;
    257     this->d = d;
    258     this->e = e;
    259     this->f = f;
    260 }
    261 void CFX_Matrix::Set(const FX_FLOAT n[6])
    262 {
    263     this->a = n[0];
    264     this->b = n[1];
    265     this->c = n[2];
    266     this->d = n[3];
    267     this->e = n[4];
    268     this->f = n[5];
    269 }
    270 void CFX_Matrix::SetReverse(const CFX_Matrix &m)
    271 {
    272     FX_FLOAT i = m.a * m.d - m.b * m.c;
    273     if (FXSYS_fabs(i) == 0) {
    274         return;
    275     }
    276     FX_FLOAT j = -i;
    277     a = m.d / i;
    278     b = m.b / j;
    279     c = m.c / j;
    280     d = m.a / i;
    281     e = (m.c * m.f - m.d * m.e) / i;
    282     f = (m.a * m.f - m.b * m.e) / j;
    283 }
    284 static void FXCRT_Matrix_Concat(CFX_Matrix &m, const CFX_Matrix &m1, const CFX_Matrix &m2)
    285 {
    286     FX_FLOAT aa = m1.a * m2.a + m1.b * m2.c;
    287     FX_FLOAT bb = m1.a * m2.b + m1.b * m2.d;
    288     FX_FLOAT cc = m1.c * m2.a + m1.d * m2.c;
    289     FX_FLOAT dd = m1.c * m2.b + m1.d * m2.d;
    290     FX_FLOAT ee = m1.e * m2.a + m1.f * m2.c + m2.e;
    291     FX_FLOAT ff = m1.e * m2.b + m1.f * m2.d + m2.f;
    292     m.a = aa, m.b = bb, m.c = cc, m.d = dd, m.e = ee, m.f = ff;
    293 }
    294 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)
    295 {
    296     CFX_Matrix m;
    297     m.Set(a, b, c, d, e, f);
    298     Concat(m, bPrepended);
    299 }
    300 void CFX_Matrix::Concat(const CFX_Matrix &m, FX_BOOL bPrepended)
    301 {
    302     if (bPrepended) {
    303         FXCRT_Matrix_Concat(*this, m, *this);
    304     } else {
    305         FXCRT_Matrix_Concat(*this, *this, m);
    306     }
    307 }
    308 void CFX_Matrix::ConcatInverse(const CFX_Matrix& src, FX_BOOL bPrepended)
    309 {
    310     CFX_Matrix m;
    311     m.SetReverse(src);
    312     Concat(m, bPrepended);
    313 }
    314 FX_BOOL CFX_Matrix::IsInvertible() const
    315 {
    316     return FXSYS_fabs(a * d - b * c) >= 0.0001f;
    317 }
    318 FX_BOOL CFX_Matrix::Is90Rotated() const
    319 {
    320     return FXSYS_fabs(a * 1000) < FXSYS_fabs(b) && FXSYS_fabs(d * 1000) < FXSYS_fabs(c);
    321 }
    322 FX_BOOL CFX_Matrix::IsScaled() const
    323 {
    324     return FXSYS_fabs(b * 1000) < FXSYS_fabs(a) && FXSYS_fabs(c * 1000) < FXSYS_fabs(d);
    325 }
    326 void CFX_Matrix::Translate(FX_FLOAT x, FX_FLOAT y, FX_BOOL bPrepended)
    327 {
    328     if (bPrepended) {
    329         e += x * a + y * c;
    330         f += y * d + x * b;
    331     } else {
    332         e += x, f += y;
    333     }
    334 }
    335 void CFX_Matrix::Scale(FX_FLOAT sx, FX_FLOAT sy, FX_BOOL bPrepended)
    336 {
    337     a *= sx, d *= sy;
    338     if (bPrepended) {
    339         b *= sx;
    340         c *= sy;
    341     } else {
    342         b *= sy;
    343         c *= sx;
    344         e *= sx;
    345         f *= sy;
    346     }
    347 }
    348 void CFX_Matrix::Rotate(FX_FLOAT fRadian, FX_BOOL bPrepended)
    349 {
    350     FX_FLOAT cosValue = FXSYS_cos(fRadian);
    351     FX_FLOAT sinValue = FXSYS_sin(fRadian);
    352     CFX_Matrix m;
    353     m.Set(cosValue, sinValue, -sinValue, cosValue, 0, 0);
    354     if (bPrepended) {
    355         FXCRT_Matrix_Concat(*this, m, *this);
    356     } else {
    357         FXCRT_Matrix_Concat(*this, *this, m);
    358     }
    359 }
    360 void CFX_Matrix::RotateAt(FX_FLOAT fRadian, FX_FLOAT dx, FX_FLOAT dy, FX_BOOL bPrepended)
    361 {
    362     Translate(dx, dy, bPrepended);
    363     Rotate(fRadian, bPrepended);
    364     Translate(-dx, -dy, bPrepended);
    365 }
    366 void CFX_Matrix::Shear(FX_FLOAT fAlphaRadian, FX_FLOAT fBetaRadian, FX_BOOL bPrepended)
    367 {
    368     CFX_Matrix m;
    369     m.Set(1, FXSYS_tan(fAlphaRadian), FXSYS_tan(fBetaRadian), 1, 0, 0);
    370     if (bPrepended) {
    371         FXCRT_Matrix_Concat(*this, m, *this);
    372     } else {
    373         FXCRT_Matrix_Concat(*this, *this, m);
    374     }
    375 }
    376 void CFX_Matrix::MatchRect(const CFX_FloatRect& dest, const CFX_FloatRect& src)
    377 {
    378     FX_FLOAT fDiff = src.left - src.right;
    379     a = FXSYS_fabs(fDiff) < 0.001f ? 1 : (dest.left - dest.right) / fDiff;
    380     fDiff = src.bottom - src.top;
    381     d = FXSYS_fabs(fDiff) < 0.001f ? 1 : (dest.bottom - dest.top) / fDiff;
    382     e = dest.left - src.left * a;
    383     f = dest.bottom - src.bottom * d;
    384     b = 0;
    385     c = 0;
    386 }
    387 FX_FLOAT CFX_Matrix::GetXUnit() const
    388 {
    389     if (b == 0) {
    390         return (a > 0 ? a : -a);
    391     }
    392     if (a == 0) {
    393         return (b > 0 ? b : -b);
    394     }
    395     return FXSYS_sqrt(a * a + b * b);
    396 }
    397 FX_FLOAT CFX_Matrix::GetYUnit() const
    398 {
    399     if (c == 0) {
    400         return (d > 0 ? d : -d);
    401     }
    402     if (d == 0) {
    403         return (c > 0 ? c : -c);
    404     }
    405     return FXSYS_sqrt(c * c + d * d);
    406 }
    407 void CFX_Matrix::GetUnitRect(CFX_RectF &rect) const
    408 {
    409     rect.left = rect.top = 0;
    410     rect.width = rect.height = 1;
    411     TransformRect(rect);
    412 }
    413 CFX_FloatRect CFX_Matrix::GetUnitRect() const
    414 {
    415     CFX_FloatRect rect(0, 0, 1, 1);
    416     rect.Transform((const CFX_Matrix*)this);
    417     return rect;
    418 }
    419 FX_FLOAT CFX_Matrix::GetUnitArea() const
    420 {
    421     FX_FLOAT A = FXSYS_sqrt(a * a + b * b);
    422     FX_FLOAT B = FXSYS_sqrt(c * c + d * d);
    423     FX_FLOAT ac = a + c, bd = b + d;
    424     FX_FLOAT C = FXSYS_sqrt(ac * ac + bd * bd);
    425     FX_FLOAT P = (A + B + C ) / 2;
    426     return FXSYS_sqrt(P * (P - A) * (P - B) * (P - C)) * 2;
    427 }
    428 FX_FLOAT CFX_Matrix::TransformXDistance(FX_FLOAT dx) const
    429 {
    430     FX_FLOAT fx = a * dx, fy = b * dx;
    431     return FXSYS_sqrt(fx * fx + fy * fy);
    432 }
    433 FX_INT32 CFX_Matrix::TransformXDistance(FX_INT32 dx) const
    434 {
    435     FX_FLOAT fx = a * dx, fy = b * dx;
    436     return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));
    437 }
    438 FX_FLOAT CFX_Matrix::TransformYDistance(FX_FLOAT dy) const
    439 {
    440     FX_FLOAT fx = c * dy, fy = d * dy;
    441     return FXSYS_sqrt(fx * fx + fy * fy);
    442 }
    443 FX_INT32 CFX_Matrix::TransformYDistance(FX_INT32 dy) const
    444 {
    445     FX_FLOAT fx = c * dy, fy = d * dy;
    446     return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));
    447 }
    448 FX_FLOAT CFX_Matrix::TransformDistance(FX_FLOAT dx, FX_FLOAT dy) const
    449 {
    450     FX_FLOAT fx = a * dx + c * dy, fy = b * dx + d * dy;
    451     return FXSYS_sqrt(fx * fx + fy * fy);
    452 }
    453 FX_INT32 CFX_Matrix::TransformDistance(FX_INT32 dx, FX_INT32 dy) const
    454 {
    455     FX_FLOAT fx = a * dx + c * dy, fy = b * dx + d * dy;
    456     return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));
    457 }
    458 FX_FLOAT CFX_Matrix::TransformDistance(FX_FLOAT distance) const
    459 {
    460     return distance * (GetXUnit() + GetYUnit()) / 2;
    461 }
    462 void CFX_Matrix::TransformVector(CFX_VectorF &v) const
    463 {
    464     FX_FLOAT fx = a * v.x + c * v.y;
    465     FX_FLOAT fy = b * v.x + d * v.y;
    466     v.x = fx, v.y = fy;
    467 }
    468 void CFX_Matrix::TransformVector(CFX_Vector &v) const
    469 {
    470     FX_FLOAT fx = a * v.x + c * v.y;
    471     FX_FLOAT fy = b * v.x + d * v.y;
    472     v.x = FXSYS_round(fx);
    473     v.y = FXSYS_round(fy);
    474 }
    475 void CFX_Matrix::TransformPoints(CFX_Point *points, FX_INT32 iCount) const
    476 {
    477     FXSYS_assert(iCount > 0);
    478     FX_FLOAT fx, fy;
    479     for (FX_INT32 i = 0; i < iCount; i ++) {
    480         fx = a * points->x + c * points->y + e;
    481         fy = b * points->x + d * points->y + f;
    482         points->x = FXSYS_round(fx);
    483         points->y = FXSYS_round(fy);
    484         points ++;
    485     }
    486 }
    487 void CFX_Matrix::TransformPoints(CFX_PointF *points, FX_INT32 iCount) const
    488 {
    489     FXSYS_assert(iCount > 0);
    490     FX_FLOAT fx, fy;
    491     for (FX_INT32 i = 0; i < iCount; i ++) {
    492         fx = a * points->x + c * points->y + e;
    493         fy = b * points->x + d * points->y + f;
    494         points->x = fx, points->y = fy;
    495         points ++;
    496     }
    497 }
    498 void CFX_Matrix::TransformPoint(FX_FLOAT &x, FX_FLOAT &y) const
    499 {
    500     FX_FLOAT fx = a * x + c * y + e;
    501     FX_FLOAT fy = b * x + d * y + f;
    502     x = fx, y = fy;
    503 }
    504 void CFX_Matrix::TransformPoint(FX_INT32 &x, FX_INT32 &y) const
    505 {
    506     FX_FLOAT fx = a * x + c * y + e;
    507     FX_FLOAT fy = b * x + d * y + f;
    508     x = FXSYS_round(fx);
    509     y = FXSYS_round(fy);
    510 }
    511 void CFX_Matrix::TransformRect(CFX_RectF &rect) const
    512 {
    513     FX_FLOAT right = rect.right(), bottom = rect.bottom();
    514     TransformRect(rect.left, right, bottom, rect.top);
    515     rect.width = right - rect.left;
    516     rect.height = bottom - rect.top;
    517 }
    518 void CFX_Matrix::TransformRect(CFX_Rect &rect) const
    519 {
    520     FX_FLOAT left = (FX_FLOAT)rect.left;
    521     FX_FLOAT top = (FX_FLOAT)rect.bottom();
    522     FX_FLOAT right = (FX_FLOAT)rect.right();
    523     FX_FLOAT bottom = (FX_FLOAT)rect.top;
    524     TransformRect(left, right, top, bottom);
    525     rect.left = FXSYS_round(left);
    526     rect.top = FXSYS_round(bottom);
    527     rect.width = FXSYS_round(right - left);
    528     rect.height = FXSYS_round(top - bottom);
    529 }
    530 void CFX_Matrix::TransformRect(FX_FLOAT& left, FX_FLOAT& right, FX_FLOAT& top, FX_FLOAT& bottom) const
    531 {
    532     FX_FLOAT x[4], y[4];
    533     x[0] = left;
    534     y[0] = top;
    535     x[1] = left;
    536     y[1] = bottom;
    537     x[2] = right;
    538     y[2] = top;
    539     x[3] = right;
    540     y[3] = bottom;
    541     int i;
    542     for (i = 0; i < 4; i ++) {
    543         Transform(x[i], y[i], x[i], y[i]);
    544     }
    545     right = left = x[0];
    546     top = bottom = y[0];
    547     for (i = 1; i < 4; i ++) {
    548         if (right < x[i]) {
    549             right = x[i];
    550         }
    551         if (left > x[i]) {
    552             left = x[i];
    553         }
    554         if (top < y[i]) {
    555             top = y[i];
    556         }
    557         if (bottom > y[i]) {
    558             bottom = y[i];
    559         }
    560     }
    561 }
    562