LCOV - code coverage report
Current view: directory - gfx/skia/src/core - SkLineClipper.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 118 0 0.0 %
Date: 2012-06-02 Functions: 7 0 0.0 %

       1                 : 
       2                 : /*
       3                 :  * Copyright 2011 Google Inc.
       4                 :  *
       5                 :  * Use of this source code is governed by a BSD-style license that can be
       6                 :  * found in the LICENSE file.
       7                 :  */
       8                 : #include "SkLineClipper.h"
       9                 : 
      10                 : // return X coordinate of intersection with horizontal line at Y
      11               0 : static SkScalar sect_with_horizontal(const SkPoint src[2], SkScalar Y) {
      12               0 :     SkScalar dy = src[1].fY - src[0].fY;
      13               0 :     if (SkScalarNearlyZero(dy)) {
      14               0 :         return SkScalarAve(src[0].fX, src[1].fX);
      15                 :     } else {
      16                 : #ifdef SK_SCALAR_IS_FLOAT
      17                 :         // need the extra precision so we don't compute a value that exceeds
      18                 :         // our original limits
      19               0 :         double X0 = src[0].fX;
      20               0 :         double Y0 = src[0].fY;
      21               0 :         double X1 = src[1].fX;
      22               0 :         double Y1 = src[1].fY;
      23               0 :         double result = X0 + ((double)Y - Y0) * (X1 - X0) / (Y1 - Y0);
      24               0 :         return (float)result;
      25                 : #else
      26                 :         return src[0].fX + SkScalarMulDiv(Y - src[0].fY, src[1].fX - src[0].fX,
      27                 :                                           dy);
      28                 : #endif
      29                 :     }
      30                 : }
      31                 : 
      32                 : // return Y coordinate of intersection with vertical line at X
      33               0 : static SkScalar sect_with_vertical(const SkPoint src[2], SkScalar X) {
      34               0 :     SkScalar dx = src[1].fX - src[0].fX;
      35               0 :     if (SkScalarNearlyZero(dx)) {
      36               0 :         return SkScalarAve(src[0].fY, src[1].fY);
      37                 :     } else {
      38                 : #ifdef SK_SCALAR_IS_FLOAT
      39                 :         // need the extra precision so we don't compute a value that exceeds
      40                 :         // our original limits
      41               0 :         double X0 = src[0].fX;
      42               0 :         double Y0 = src[0].fY;
      43               0 :         double X1 = src[1].fX;
      44               0 :         double Y1 = src[1].fY;
      45               0 :         double result = Y0 + ((double)X - X0) * (Y1 - Y0) / (X1 - X0);
      46               0 :         return (float)result;
      47                 : #else
      48                 :         return src[0].fY + SkScalarMulDiv(X - src[0].fX, src[1].fY - src[0].fY,
      49                 :                                           dx);
      50                 : #endif
      51                 :     }
      52                 : }
      53                 : 
      54                 : ///////////////////////////////////////////////////////////////////////////////
      55                 : 
      56               0 : static inline bool nestedLT(SkScalar a, SkScalar b, SkScalar dim) {
      57               0 :     return a <= b && (a < b || dim > 0);
      58                 : }
      59                 : 
      60                 : // returns true if outer contains inner, even if inner is empty.
      61                 : // note: outer.contains(inner) always returns false if inner is empty.
      62               0 : static inline bool containsNoEmptyCheck(const SkRect& outer,
      63                 :                                         const SkRect& inner) {
      64                 :     return  outer.fLeft <= inner.fLeft && outer.fTop <= inner.fTop &&
      65               0 :             outer.fRight >= inner.fRight && outer.fBottom >= inner.fBottom;
      66                 : }
      67                 : 
      68               0 : bool SkLineClipper::IntersectLine(const SkPoint src[2], const SkRect& clip,
      69                 :                                   SkPoint dst[2]) {
      70                 :     SkRect bounds;
      71                 :     
      72               0 :     bounds.set(src, 2);
      73               0 :     if (containsNoEmptyCheck(clip, bounds)) {
      74               0 :         if (src != dst) {
      75               0 :             memcpy(dst, src, 2 * sizeof(SkPoint));
      76                 :         }
      77               0 :         return true;
      78                 :     }
      79                 :     // check for no overlap, and only permit coincident edges if the line
      80                 :     // and the edge are colinear
      81               0 :     if (nestedLT(bounds.fRight, clip.fLeft, bounds.width()) ||
      82               0 :         nestedLT(clip.fRight, bounds.fLeft, bounds.width()) ||
      83               0 :         nestedLT(bounds.fBottom, clip.fTop, bounds.height()) ||
      84               0 :         nestedLT(clip.fBottom, bounds.fTop, bounds.height())) {
      85               0 :         return false;
      86                 :     }
      87                 : 
      88                 :     int index0, index1;
      89                 :     
      90               0 :     if (src[0].fY < src[1].fY) {
      91               0 :         index0 = 0;
      92               0 :         index1 = 1;
      93                 :     } else {
      94               0 :         index0 = 1;
      95               0 :         index1 = 0;
      96                 :     }
      97                 : 
      98                 :     SkPoint tmp[2];
      99               0 :     memcpy(tmp, src, sizeof(tmp));
     100                 : 
     101                 :     // now compute Y intersections
     102               0 :     if (tmp[index0].fY < clip.fTop) {
     103               0 :         tmp[index0].set(sect_with_horizontal(src, clip.fTop), clip.fTop);
     104                 :     }
     105               0 :     if (tmp[index1].fY > clip.fBottom) {
     106               0 :         tmp[index1].set(sect_with_horizontal(src, clip.fBottom), clip.fBottom);
     107                 :     }
     108                 :     
     109               0 :     if (tmp[0].fX < tmp[1].fX) {
     110               0 :         index0 = 0;
     111               0 :         index1 = 1;
     112                 :     } else {
     113               0 :         index0 = 1;
     114               0 :         index1 = 0;
     115                 :     }
     116                 : 
     117                 :     // check for quick-reject in X again, now that we may have been chopped
     118               0 :     if ((tmp[index1].fX <= clip.fLeft || tmp[index0].fX >= clip.fRight) &&
     119                 :         tmp[index0].fX < tmp[index1].fX) {
     120                 :         // only reject if we have a non-zero width
     121               0 :         return false;
     122                 :     }
     123                 : 
     124               0 :     if (tmp[index0].fX < clip.fLeft) {
     125               0 :         tmp[index0].set(clip.fLeft, sect_with_vertical(src, clip.fLeft));
     126                 :     }
     127               0 :     if (tmp[index1].fX > clip.fRight) {
     128               0 :         tmp[index1].set(clip.fRight, sect_with_vertical(src, clip.fRight));
     129                 :     }
     130                 : #ifdef SK_DEBUG
     131               0 :     bounds.set(tmp, 2);
     132               0 :     SkASSERT(containsNoEmptyCheck(clip, bounds));
     133                 : #endif
     134               0 :     memcpy(dst, tmp, sizeof(tmp));
     135               0 :     return true;
     136                 : }
     137                 : 
     138                 : #ifdef SK_DEBUG
     139                 : // return value between the two limits, where the limits are either ascending
     140                 : // or descending.
     141               0 : static bool is_between_unsorted(SkScalar value,
     142                 :                                 SkScalar limit0, SkScalar limit1) {
     143               0 :     if (limit0 < limit1) {
     144               0 :         return limit0 <= value && value <= limit1;
     145                 :     } else {
     146               0 :         return limit1 <= value && value <= limit0;
     147                 :     }
     148                 : }
     149                 : #endif
     150                 : 
     151               0 : int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip,
     152                 :                             SkPoint lines[]) {
     153                 :     int index0, index1;
     154                 : 
     155               0 :     if (pts[0].fY < pts[1].fY) {
     156               0 :         index0 = 0;
     157               0 :         index1 = 1;
     158                 :     } else {
     159               0 :         index0 = 1;
     160               0 :         index1 = 0;
     161                 :     }
     162                 : 
     163                 :     // Check if we're completely clipped out in Y (above or below
     164                 : 
     165               0 :     if (pts[index1].fY <= clip.fTop) {  // we're above the clip
     166               0 :         return 0;
     167                 :     }
     168               0 :     if (pts[index0].fY >= clip.fBottom) {  // we're below the clip
     169               0 :         return 0;
     170                 :     }
     171                 :     
     172                 :     // Chop in Y to produce a single segment, stored in tmp[0..1]
     173                 : 
     174                 :     SkPoint tmp[2];
     175               0 :     memcpy(tmp, pts, sizeof(tmp));
     176                 : 
     177                 :     // now compute intersections
     178               0 :     if (pts[index0].fY < clip.fTop) {
     179               0 :         tmp[index0].set(sect_with_horizontal(pts, clip.fTop), clip.fTop);
     180               0 :         SkASSERT(is_between_unsorted(tmp[index0].fX, pts[0].fX, pts[1].fX));
     181                 :     }
     182               0 :     if (tmp[index1].fY > clip.fBottom) {
     183               0 :         tmp[index1].set(sect_with_horizontal(pts, clip.fBottom), clip.fBottom);
     184               0 :         SkASSERT(is_between_unsorted(tmp[index1].fX, pts[0].fX, pts[1].fX));
     185                 :     }
     186                 : 
     187                 :     // Chop it into 1..3 segments that are wholly within the clip in X.
     188                 : 
     189                 :     // temp storage for up to 3 segments
     190                 :     SkPoint resultStorage[kMaxPoints];
     191                 :     SkPoint* result;    // points to our results, either tmp or resultStorage
     192               0 :     int lineCount = 1;
     193                 :     bool reverse;
     194                 : 
     195               0 :     if (pts[0].fX < pts[1].fX) {
     196               0 :         index0 = 0;
     197               0 :         index1 = 1;
     198               0 :         reverse = false;
     199                 :     } else {
     200               0 :         index0 = 1;
     201               0 :         index1 = 0;
     202               0 :         reverse = true;
     203                 :     }
     204                 : 
     205               0 :     if (tmp[index1].fX <= clip.fLeft) {  // wholly to the left
     206               0 :         tmp[0].fX = tmp[1].fX = clip.fLeft;
     207               0 :         result = tmp;
     208               0 :         reverse = false;
     209               0 :     } else if (tmp[index0].fX >= clip.fRight) {    // wholly to the right
     210               0 :         tmp[0].fX = tmp[1].fX = clip.fRight;
     211               0 :         result = tmp;
     212               0 :         reverse = false;
     213                 :     } else {
     214               0 :         result = resultStorage;
     215               0 :         SkPoint* r = result;
     216                 :         
     217               0 :         if (tmp[index0].fX < clip.fLeft) {
     218               0 :             r->set(clip.fLeft, tmp[index0].fY);
     219               0 :             r += 1;
     220               0 :             r->set(clip.fLeft, sect_with_vertical(tmp, clip.fLeft));
     221               0 :             SkASSERT(is_between_unsorted(r->fY, tmp[0].fY, tmp[1].fY));
     222                 :         } else {
     223               0 :             *r = tmp[index0];
     224                 :         }
     225               0 :         r += 1;
     226                 : 
     227               0 :         if (tmp[index1].fX > clip.fRight) {
     228               0 :             r->set(clip.fRight, sect_with_vertical(tmp, clip.fRight));
     229               0 :             SkASSERT(is_between_unsorted(r->fY, tmp[0].fY, tmp[1].fY));
     230               0 :             r += 1;
     231               0 :             r->set(clip.fRight, tmp[index1].fY);
     232                 :         } else {
     233               0 :             *r = tmp[index1];
     234                 :         }
     235                 : 
     236               0 :         lineCount = r - result;
     237                 :     }
     238                 : 
     239                 :     // Now copy the results into the caller's lines[] parameter
     240               0 :     if (reverse) {
     241                 :         // copy the pts in reverse order to maintain winding order
     242               0 :         for (int i = 0; i <= lineCount; i++) {
     243               0 :             lines[lineCount - i] = result[i];
     244                 :         }
     245                 :     } else {
     246               0 :         memcpy(lines, result, (lineCount + 1) * sizeof(SkPoint));
     247                 :     }
     248               0 :     return lineCount;
     249                 : }
     250                 : 

Generated by: LCOV version 1.7