fix winding bug in lineclipper
authorreed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 23 Nov 2009 20:10:41 +0000 (20:10 +0000)
committerreed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 23 Nov 2009 20:10:41 +0000 (20:10 +0000)
expose path.dump() all the time
UP arrow now toggles a grid of clip rects in sample app

git-svn-id: http://skia.googlecode.com/svn/trunk@443 2bbb7eff-a529-9590-31e7-b0007b416f81

include/core/SkPath.h
include/views/SkView.h
samplecode/SampleApp.cpp
src/core/SkLineClipper.cpp
src/core/SkPath.cpp

index 6d4d670c4ae1df1c353b0e84583c8bde791ae871..ecdfd1ab4146c5359ad38b879c8b68d2600ac333 100644 (file)
@@ -547,11 +547,8 @@ public:
         Verb autoClose(SkPoint pts[2]);
     };
 
-#ifdef SK_DEBUG
-  /** @cond UNIT_TEST */
     void dump(bool forceClose, const char title[] = NULL) const;
-  /** @endcond */
-#endif
+    void dump() const;
 
     void flatten(SkFlattenableWriteBuffer&) const;
     void unflatten(SkFlattenableReadBuffer&);
index f3b729f443128867a7aefae9237a67f6150e775f..fc36d34fca06470893e1933d87c8b6ab0a44db56 100644 (file)
@@ -96,7 +96,8 @@ public:
     void        offset(SkScalar dx, SkScalar dy);
 
     /** Call this to have the view draw into the specified canvas. */
-    void        draw(SkCanvas* canvas);
+    virtual void draw(SkCanvas* canvas);
+
     /** Call this to invalidate part of all of a view, requesting that the view's
         draw method be called. The rectangle parameter specifies the part of the view
         that should be redrawn. If it is null, it specifies the entire view bounds.
index c485356b1faa635518e99b30bd4768715e6605e1..2d0da1f71b27f052ad0b69b8b4ba2b2ac253ac6d 100644 (file)
@@ -129,6 +129,8 @@ public:
        SampleWindow(void* hwnd);
        virtual ~SampleWindow();
 
+    virtual void draw(SkCanvas* canvas);
+
 protected:
     virtual void onDraw(SkCanvas* canvas);
        virtual bool onHandleKey(SkKey key);
@@ -167,6 +169,7 @@ private:
     CanvasType fCanvasType;
 
     bool fUseClip;
+    bool fNClip;
     bool fRepeatDrawing;
     bool fAnimating;
     bool fRotate;
@@ -210,6 +213,7 @@ SampleWindow::SampleWindow(void* hwnd) : INHERITED(hwnd) {
 
     fCanvasType = kRaster_CanvasType;
     fUseClip = false;
+    fNClip = false;
     fRepeatDrawing = false;
     fAnimating = false;
     fRotate = false;
@@ -237,6 +241,33 @@ SampleWindow::~SampleWindow() {
     delete fGLCanvas;
 }
 
+#define XCLIP_N  4
+#define YCLIP_N  1
+
+void SampleWindow::draw(SkCanvas* canvas) {
+    if (fNClip) {
+     //   this->INHERITED::draw(canvas);
+     //   SkBitmap orig = capture_bitmap(canvas);
+
+        const SkScalar w = this->width();
+        const SkScalar h = this->height();
+        const SkScalar cw = w / XCLIP_N;
+        const SkScalar ch = h / YCLIP_N;
+        for (int y = 0; y < YCLIP_N; y++) {
+            for (int x = 0; x < XCLIP_N; x++) {
+                SkAutoCanvasRestore acr(canvas, true);
+                SkRect r = {
+                    x * cw, y * ch, (x + 1) * cw, (y + 1) * ch
+                };
+                canvas->clipRect(r);
+                this->INHERITED::draw(canvas);
+            }
+        }
+    } else {
+        this->INHERITED::draw(canvas);
+    }
+}
+
 void SampleWindow::onDraw(SkCanvas* canvas) {
     if (fRepeatDrawing) {
         this->inval(NULL);
@@ -511,7 +542,7 @@ bool SampleWindow::onHandleKey(SkKey key) {
             this->inval(NULL);
             return true;
         case kUp_SkKey:
-            fUseClip = !fUseClip;
+            fNClip = !fNClip;
             this->updateTitle();
             this->inval(NULL);
             return true;
@@ -604,7 +635,9 @@ void SampleWindow::updateTitle() {
     if (fRotate) {
         title.prepend("<R> ");
     }
-    
+    if (fNClip) {
+        title.prepend("<C> ");
+    }
     this->setTitle(title.c_str());
 }
 
index 9164f7c13f3087fd2a608a8ad49745b3ec3dee95..58bf6033a71bdeea7f6b33b76a6f97f0994343af 100644 (file)
@@ -124,21 +124,26 @@ int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip,
     SkPoint resultStorage[kMaxPoints];
     SkPoint* result;    // points to our results, either tmp or resultStorage
     int lineCount = 1;
+    bool reverse;
 
     if (pts[0].fX < pts[1].fX) {
         index0 = 0;
         index1 = 1;
+        reverse = false;
     } else {
         index0 = 1;
         index1 = 0;
+        reverse = true;
     }
-    
+
     if (tmp[index1].fX <= clip.fLeft) {  // wholly to the left
         tmp[0].fX = tmp[1].fX = clip.fLeft;
         result = tmp;
+        reverse = false;
     } else if (tmp[index0].fX >= clip.fRight) {    // wholly to the right
         tmp[0].fX = tmp[1].fX = clip.fRight;
         result = tmp;
+        reverse = false;
     } else {
         result = resultStorage;
         SkPoint* r = result;
@@ -164,7 +169,7 @@ int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip,
     }
 
     // Now copy the results into the caller's lines[] parameter
-    if (0 == index1) {
+    if (reverse) {
         // copy the pts in reverse order to maintain winding order
         for (int i = 0; i <= lineCount; i++) {
             lines[lineCount - i] = result[i];
index 63c3eb06fa51fc9b1a7ead2328d9fe1fd5da2a01..55be129ba0cac63343a88af2620ff5816e77a0a0 100644 (file)
@@ -1222,30 +1222,6 @@ void SkPath::unflatten(SkFlattenableReadBuffer& buffer) {
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
-#ifdef SK_DEBUG
-
-void SkPath::validate() const {
-    SkASSERT(this != NULL);
-    SkASSERT((fFillType & ~3) == 0);
-    fPts.validate();
-    fVerbs.validate();
-
-    if (!fBoundsIsDirty) {
-        SkRect bounds;
-        compute_pt_bounds(&bounds, fPts);
-        if (fPts.count() <= 1) {
-            // if we're empty, fBounds may be empty but translated, so we can't
-            // necessarily compare to bounds directly
-            // try path.addOval(2, 2, 2, 2) which is empty, but the bounds will
-            // be [2, 2, 2, 2]
-            SkASSERT(bounds.isEmpty());
-            SkASSERT(fBounds.isEmpty());
-        } else {
-            fBounds.contains(bounds);
-        }
-    }
-}
-
 void SkPath::dump(bool forceClose, const char title[]) const {
     Iter    iter(*this, forceClose);
     SkPoint pts[4];
@@ -1306,4 +1282,31 @@ void SkPath::dump(bool forceClose, const char title[]) const {
     SkDebugf("path: done %s\n", title ? title : "");
 }
 
+void SkPath::dump() const {
+    this->dump(false);
+}
+
+#ifdef SK_DEBUG
+void SkPath::validate() const {
+    SkASSERT(this != NULL);
+    SkASSERT((fFillType & ~3) == 0);
+    fPts.validate();
+    fVerbs.validate();
+    
+    if (!fBoundsIsDirty) {
+        SkRect bounds;
+        compute_pt_bounds(&bounds, fPts);
+        if (fPts.count() <= 1) {
+            // if we're empty, fBounds may be empty but translated, so we can't
+            // necessarily compare to bounds directly
+            // try path.addOval(2, 2, 2, 2) which is empty, but the bounds will
+            // be [2, 2, 2, 2]
+            SkASSERT(bounds.isEmpty());
+            SkASSERT(fBounds.isEmpty());
+        } else {
+            fBounds.contains(bounds);
+        }
+    }
+}
 #endif
+