diff --git a/gfx/public/nsIRenderingContext.h b/gfx/public/nsIRenderingContext.h index 5597b5d8a66..113a370d934 100644 --- a/gfx/public/nsIRenderingContext.h +++ b/gfx/public/nsIRenderingContext.h @@ -303,6 +303,16 @@ public: */ NS_IMETHOD DrawLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1) = 0; + + /** + * Draw a line without being transformed + * @param aXO starting horiztonal coord in twips + * @param aY0 starting vertical coord in twips + * @param aX1 end horiztonal coord in twips + * @param aY1 end vertical coord in twips + */ + NS_IMETHOD DrawStdLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1) = 0; + /** * Draw a polyline * @param aPoints array of endpoints diff --git a/gfx/public/nsRenderingContextImpl.h b/gfx/public/nsRenderingContextImpl.h index 9f12647b98f..2e0ebc906ef 100644 --- a/gfx/public/nsRenderingContextImpl.h +++ b/gfx/public/nsRenderingContextImpl.h @@ -53,6 +53,12 @@ public: */ NS_IMETHOD DrawPath(nsPathPoint aPointArray[],PRInt32 aNumPts); + /** --------------------------------------------------- + * See documentation in nsIRenderingContext.h + * @update 05/01/00 dwc + */ + NS_IMETHOD DrawStdLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1) { return NS_OK;} + protected: virtual ~nsRenderingContextImpl(); @@ -77,6 +83,7 @@ protected: void TileImage(nsDrawingSurface aDS,nsRect &aSrcRect,PRInt16 aWidth,PRInt16 aHeight); + public: }; @@ -102,11 +109,9 @@ public: * Divide a Quadratic curve into line segments if it is not smaller than a certain size * else it is so small that it can be approximated by 2 lineto calls * @param aRenderingContext -- The RenderingContext to use to draw with - * @param aPointArray[] -- A list of points we can put line calls into instead of drawing. If null, lines are drawn - * @param aCurInex -- a pointer to an Integer that tells were to put the points into the array, incremented when finished * @update 3/26/99 dwc */ - void SubDivide(nsIRenderingContext *aRenderingContext,nsPoint aPointArray[],PRInt32 *aCurIndex); + void SubDivide(nsIRenderingContext *aRenderingContext); /** --------------------------------------------------- * Divide a Quadratic Bezier curve at the mid-point diff --git a/gfx/src/nsRenderingContextImpl.cpp b/gfx/src/nsRenderingContextImpl.cpp index 2c1453c4ba3..cfeaf895191 100644 --- a/gfx/src/nsRenderingContextImpl.cpp +++ b/gfx/src/nsRenderingContextImpl.cpp @@ -164,17 +164,23 @@ nsPathIter::eSegType curveType; pp0 = &pts[0]; } pp = pp0; + np = &aPointArray[0]; for ( i= 0; i < aNumPts; i++,np++,pp++){ pp->x = np->x; pp->y = np->y; + pp->mIsOnCurve = np->mIsOnCurve; mTranMatrix->TransformCoord((int*)&pp->x,(int*)&pp->y); } - thePathIter = new nsPathIter(pp0,aNumPts); while ( thePathIter->NextSeg(thecurve,curveType) ) { - //thecurve.Display_Graphic(TheProcess,NULL); + // draw the curve we found + if(eLINE == curveType){ + DrawStdLine(thecurve.mAnc1.x,thecurve.mAnc1.y,thecurve.mAnc2.x,thecurve.mAnc2.y); + } else { + thecurve.SubDivide(this); + } } // Release temporary storage if necessary @@ -216,7 +222,7 @@ PRInt32 flag = NS_COPYBITS_TO_BACK_BUFFER | NS_COPYBITS_XFORM_DEST_VALUES; * @update 3/29/00 dwc */ void -QBezierCurve::SubDivide(nsIRenderingContext *aRenderingContext,nsPoint aPointArray[],PRInt32 *aCurIndex) +QBezierCurve::SubDivide(nsIRenderingContext *aRenderingContext) { QBezierCurve curve1,curve2; PRInt16 fx,fy,smag; @@ -228,30 +234,19 @@ PRInt16 fx,fy,smag; // for now to fix the build //fx = (PRInt16)abs(curve1.mAnc2.x - this->mCon.x); //fy = (PRInt16)abs(curve1.mAnc2.y - this->mCon.y); - fx = 1; - fy = 1; + fx = fy = 1; smag = fx+fy-(PR_MIN(fx,fy)>>1); //smag = fx*fx + fy*fy; if (smag>1){ // split the curve again - curve1.SubDivide(aRenderingContext,aPointArray,aCurIndex); - curve2.SubDivide(aRenderingContext,aPointArray,aCurIndex); + curve1.SubDivide(aRenderingContext); + curve2.SubDivide(aRenderingContext); }else{ - if(aPointArray ) { - // save the points for further processing - aPointArray[*aCurIndex].x = curve1.mAnc2.x; - aPointArray[*aCurIndex].y = curve1.mAnc2.y; - (*aCurIndex)++; - aPointArray[*aCurIndex].x = curve2.mAnc2.x; - aPointArray[*aCurIndex].y = curve2.mAnc2.y; - (*aCurIndex)++; - }else{ - // draw the curve - aRenderingContext->DrawLine(curve1.mAnc1.x,curve1.mAnc1.y,curve1.mAnc2.x,curve1.mAnc2.y); - aRenderingContext->DrawLine(curve1.mAnc2.x,curve1.mAnc2.y,curve2.mAnc2.x,curve2.mAnc2.y); - } + // draw the curve + aRenderingContext->DrawStdLine(curve1.mAnc1.x,curve1.mAnc1.y,curve1.mAnc2.x,curve1.mAnc2.y); + aRenderingContext->DrawStdLine(curve1.mAnc2.x,curve1.mAnc2.y,curve2.mAnc2.x,curve2.mAnc2.y); } } @@ -318,8 +313,8 @@ nsPathIter::nsPathIter(nsPathPoint* aThePath,PRUint32 aNumPts) PRBool nsPathIter::NextSeg(QBezierCurve& TheSegment,eSegType& aCurveType) { -PRInt8 code=0; -PRBool result = PR_FALSE; +PRInt8 code=0,number=1; +PRBool result = PR_TRUE; nsPathPoint *pt1,*pt2,*pt3; nsPathPoint ptAvg,ptAvg1; @@ -329,68 +324,74 @@ nsPathPoint ptAvg,ptAvg1; pt1 = &(mThePath[mCurPoint]); if(PR_TRUE == pt1->mIsOnCurve) { code += 0x04; - } - + } // 2nd point if ( (mCurPoint+1) < mNumPoints) { + number++; pt2 = &(mThePath[mCurPoint+1]); - } else{ - pt2 = &(mThePath[0]); - } - if(PR_TRUE == pt2->mIsOnCurve) { - code += 0x02; - } + if(PR_TRUE == pt2->mIsOnCurve) { + code += 0x02; + } - // 3rd point - if( (mCurPoint+2) < mNumPoints) { - pt3 = &(mThePath[mCurPoint+2]); - } else if ( (mCurPoint+1) < mNumPoints) { - pt3 = &(mThePath[0]); - } else { - pt3 = &(mThePath[1]); - } - if(PR_TRUE == pt3->mIsOnCurve) { - code += 0x01; - } - - switch(code) { - case 07: // 111 - case 06: // 110 + // 3rd point + if( (mCurPoint+2) < mNumPoints) { + number++; + pt3 = &(mThePath[mCurPoint+2]); + if(PR_TRUE == pt3->mIsOnCurve) { + code += 0x01; + } + // have all three points.. + switch(code) { + case 07: // 111 + case 06: // 110 + TheSegment.SetPoints(pt1->x,pt1->y,0,0,pt2->x,pt2->y); + aCurveType = eLINE; + mCurPoint++; + break; + case 05: // 101 + TheSegment.SetPoints(pt1->x,pt1->y,pt2->x,pt2->y,pt3->x,pt3->y); + aCurveType = eQCURVE; + mCurPoint+=2; + break; + case 04: // 100 + ptAvg.x = (nscoord) (((pt2->x+pt3->x)/2.0)); + ptAvg.y = (nscoord) (((pt2->y+pt3->y)/2.0)); + TheSegment.SetPoints(pt1->x,pt1->y,pt2->x,pt2->y,ptAvg.x,ptAvg.y); + aCurveType = eQCURVE; + mCurPoint++; + case 03: // 011 + case 02: // 010 + TheSegment.SetPoints(pt1->x,pt1->y,0,0,pt2->x,pt2->y); + aCurveType = eLINE; + mCurPoint++; + case 01: // 001 + ptAvg.x = (nscoord) (((pt1->x+pt2->x)/2.0)); + ptAvg.y = (nscoord) (((pt1->y+pt2->y)/2.0)); + TheSegment.SetPoints(ptAvg.x,ptAvg.y,pt2->x,pt3->y,pt2->x,pt3->y); + aCurveType = eQCURVE; + mCurPoint+=2; + case 00: // 000 + ptAvg.x = (nscoord) (((pt1->x+pt2->x)/2.0)); + ptAvg.y = (nscoord) (((pt1->y+pt2->y)/2.0)); + ptAvg1.x = (nscoord) (((pt2->x+pt3->x)/2.0)); + ptAvg1.y = (nscoord) (((pt2->y+pt3->y)/2.0)); + TheSegment.SetPoints(ptAvg.x,ptAvg.y,pt2->x,pt2->y,ptAvg1.x,ptAvg1.y); + default: + break; + } + } else { + // have two points.. draw a line TheSegment.SetPoints(pt1->x,pt1->y,0,0,pt2->x,pt2->y); aCurveType = eLINE; mCurPoint++; - break; - case 05: // 101 - TheSegment.SetPoints(pt1->x,pt1->y,pt2->x,pt2->y,pt3->x,pt3->y); - aCurveType = eQCURVE; - mCurPoint+=2; - break; - case 04: // 100 - ptAvg.x = (nscoord) (((pt2->x+pt3->x)/2.0)); - ptAvg.y = (nscoord) (((pt2->y+pt3->y)/2.0)); - TheSegment.SetPoints(pt1->x,pt1->y,pt2->x,pt2->y,ptAvg.x,ptAvg.y); - aCurveType = eQCURVE; - mCurPoint++; - case 03: // 011 - case 02: // 010 - TheSegment.SetPoints(pt1->x,pt1->y,0,0,pt2->x,pt2->y); - aCurveType = eLINE; - mCurPoint++; - case 01: // 001 - ptAvg.x = (nscoord) (((pt1->x+pt2->x)/2.0)); - ptAvg.y = (nscoord) (((pt1->y+pt2->y)/2.0)); - TheSegment.SetPoints(ptAvg.x,ptAvg.y,pt2->x,pt3->y,pt2->x,pt3->y); - aCurveType = eQCURVE; - mCurPoint+=2; - case 00: // 000 - ptAvg.x = (nscoord) (((pt1->x+pt2->x)/2.0)); - ptAvg.y = (nscoord) (((pt1->y+pt2->y)/2.0)); - ptAvg1.x = (nscoord) (((pt2->x+pt3->x)/2.0)); - ptAvg1.y = (nscoord) (((pt2->y+pt3->y)/2.0)); - TheSegment.SetPoints(ptAvg.x,ptAvg.y,pt2->x,pt2->y,ptAvg1.x,ptAvg1.y); - default: - break; + } + } else { + // just have one point + result = PR_FALSE; } + } else { + // all finished + result = PR_FALSE; } return result; diff --git a/gfx/src/shared/nsRenderingContextImpl.cpp b/gfx/src/shared/nsRenderingContextImpl.cpp index 2c1453c4ba3..cfeaf895191 100644 --- a/gfx/src/shared/nsRenderingContextImpl.cpp +++ b/gfx/src/shared/nsRenderingContextImpl.cpp @@ -164,17 +164,23 @@ nsPathIter::eSegType curveType; pp0 = &pts[0]; } pp = pp0; + np = &aPointArray[0]; for ( i= 0; i < aNumPts; i++,np++,pp++){ pp->x = np->x; pp->y = np->y; + pp->mIsOnCurve = np->mIsOnCurve; mTranMatrix->TransformCoord((int*)&pp->x,(int*)&pp->y); } - thePathIter = new nsPathIter(pp0,aNumPts); while ( thePathIter->NextSeg(thecurve,curveType) ) { - //thecurve.Display_Graphic(TheProcess,NULL); + // draw the curve we found + if(eLINE == curveType){ + DrawStdLine(thecurve.mAnc1.x,thecurve.mAnc1.y,thecurve.mAnc2.x,thecurve.mAnc2.y); + } else { + thecurve.SubDivide(this); + } } // Release temporary storage if necessary @@ -216,7 +222,7 @@ PRInt32 flag = NS_COPYBITS_TO_BACK_BUFFER | NS_COPYBITS_XFORM_DEST_VALUES; * @update 3/29/00 dwc */ void -QBezierCurve::SubDivide(nsIRenderingContext *aRenderingContext,nsPoint aPointArray[],PRInt32 *aCurIndex) +QBezierCurve::SubDivide(nsIRenderingContext *aRenderingContext) { QBezierCurve curve1,curve2; PRInt16 fx,fy,smag; @@ -228,30 +234,19 @@ PRInt16 fx,fy,smag; // for now to fix the build //fx = (PRInt16)abs(curve1.mAnc2.x - this->mCon.x); //fy = (PRInt16)abs(curve1.mAnc2.y - this->mCon.y); - fx = 1; - fy = 1; + fx = fy = 1; smag = fx+fy-(PR_MIN(fx,fy)>>1); //smag = fx*fx + fy*fy; if (smag>1){ // split the curve again - curve1.SubDivide(aRenderingContext,aPointArray,aCurIndex); - curve2.SubDivide(aRenderingContext,aPointArray,aCurIndex); + curve1.SubDivide(aRenderingContext); + curve2.SubDivide(aRenderingContext); }else{ - if(aPointArray ) { - // save the points for further processing - aPointArray[*aCurIndex].x = curve1.mAnc2.x; - aPointArray[*aCurIndex].y = curve1.mAnc2.y; - (*aCurIndex)++; - aPointArray[*aCurIndex].x = curve2.mAnc2.x; - aPointArray[*aCurIndex].y = curve2.mAnc2.y; - (*aCurIndex)++; - }else{ - // draw the curve - aRenderingContext->DrawLine(curve1.mAnc1.x,curve1.mAnc1.y,curve1.mAnc2.x,curve1.mAnc2.y); - aRenderingContext->DrawLine(curve1.mAnc2.x,curve1.mAnc2.y,curve2.mAnc2.x,curve2.mAnc2.y); - } + // draw the curve + aRenderingContext->DrawStdLine(curve1.mAnc1.x,curve1.mAnc1.y,curve1.mAnc2.x,curve1.mAnc2.y); + aRenderingContext->DrawStdLine(curve1.mAnc2.x,curve1.mAnc2.y,curve2.mAnc2.x,curve2.mAnc2.y); } } @@ -318,8 +313,8 @@ nsPathIter::nsPathIter(nsPathPoint* aThePath,PRUint32 aNumPts) PRBool nsPathIter::NextSeg(QBezierCurve& TheSegment,eSegType& aCurveType) { -PRInt8 code=0; -PRBool result = PR_FALSE; +PRInt8 code=0,number=1; +PRBool result = PR_TRUE; nsPathPoint *pt1,*pt2,*pt3; nsPathPoint ptAvg,ptAvg1; @@ -329,68 +324,74 @@ nsPathPoint ptAvg,ptAvg1; pt1 = &(mThePath[mCurPoint]); if(PR_TRUE == pt1->mIsOnCurve) { code += 0x04; - } - + } // 2nd point if ( (mCurPoint+1) < mNumPoints) { + number++; pt2 = &(mThePath[mCurPoint+1]); - } else{ - pt2 = &(mThePath[0]); - } - if(PR_TRUE == pt2->mIsOnCurve) { - code += 0x02; - } + if(PR_TRUE == pt2->mIsOnCurve) { + code += 0x02; + } - // 3rd point - if( (mCurPoint+2) < mNumPoints) { - pt3 = &(mThePath[mCurPoint+2]); - } else if ( (mCurPoint+1) < mNumPoints) { - pt3 = &(mThePath[0]); - } else { - pt3 = &(mThePath[1]); - } - if(PR_TRUE == pt3->mIsOnCurve) { - code += 0x01; - } - - switch(code) { - case 07: // 111 - case 06: // 110 + // 3rd point + if( (mCurPoint+2) < mNumPoints) { + number++; + pt3 = &(mThePath[mCurPoint+2]); + if(PR_TRUE == pt3->mIsOnCurve) { + code += 0x01; + } + // have all three points.. + switch(code) { + case 07: // 111 + case 06: // 110 + TheSegment.SetPoints(pt1->x,pt1->y,0,0,pt2->x,pt2->y); + aCurveType = eLINE; + mCurPoint++; + break; + case 05: // 101 + TheSegment.SetPoints(pt1->x,pt1->y,pt2->x,pt2->y,pt3->x,pt3->y); + aCurveType = eQCURVE; + mCurPoint+=2; + break; + case 04: // 100 + ptAvg.x = (nscoord) (((pt2->x+pt3->x)/2.0)); + ptAvg.y = (nscoord) (((pt2->y+pt3->y)/2.0)); + TheSegment.SetPoints(pt1->x,pt1->y,pt2->x,pt2->y,ptAvg.x,ptAvg.y); + aCurveType = eQCURVE; + mCurPoint++; + case 03: // 011 + case 02: // 010 + TheSegment.SetPoints(pt1->x,pt1->y,0,0,pt2->x,pt2->y); + aCurveType = eLINE; + mCurPoint++; + case 01: // 001 + ptAvg.x = (nscoord) (((pt1->x+pt2->x)/2.0)); + ptAvg.y = (nscoord) (((pt1->y+pt2->y)/2.0)); + TheSegment.SetPoints(ptAvg.x,ptAvg.y,pt2->x,pt3->y,pt2->x,pt3->y); + aCurveType = eQCURVE; + mCurPoint+=2; + case 00: // 000 + ptAvg.x = (nscoord) (((pt1->x+pt2->x)/2.0)); + ptAvg.y = (nscoord) (((pt1->y+pt2->y)/2.0)); + ptAvg1.x = (nscoord) (((pt2->x+pt3->x)/2.0)); + ptAvg1.y = (nscoord) (((pt2->y+pt3->y)/2.0)); + TheSegment.SetPoints(ptAvg.x,ptAvg.y,pt2->x,pt2->y,ptAvg1.x,ptAvg1.y); + default: + break; + } + } else { + // have two points.. draw a line TheSegment.SetPoints(pt1->x,pt1->y,0,0,pt2->x,pt2->y); aCurveType = eLINE; mCurPoint++; - break; - case 05: // 101 - TheSegment.SetPoints(pt1->x,pt1->y,pt2->x,pt2->y,pt3->x,pt3->y); - aCurveType = eQCURVE; - mCurPoint+=2; - break; - case 04: // 100 - ptAvg.x = (nscoord) (((pt2->x+pt3->x)/2.0)); - ptAvg.y = (nscoord) (((pt2->y+pt3->y)/2.0)); - TheSegment.SetPoints(pt1->x,pt1->y,pt2->x,pt2->y,ptAvg.x,ptAvg.y); - aCurveType = eQCURVE; - mCurPoint++; - case 03: // 011 - case 02: // 010 - TheSegment.SetPoints(pt1->x,pt1->y,0,0,pt2->x,pt2->y); - aCurveType = eLINE; - mCurPoint++; - case 01: // 001 - ptAvg.x = (nscoord) (((pt1->x+pt2->x)/2.0)); - ptAvg.y = (nscoord) (((pt1->y+pt2->y)/2.0)); - TheSegment.SetPoints(ptAvg.x,ptAvg.y,pt2->x,pt3->y,pt2->x,pt3->y); - aCurveType = eQCURVE; - mCurPoint+=2; - case 00: // 000 - ptAvg.x = (nscoord) (((pt1->x+pt2->x)/2.0)); - ptAvg.y = (nscoord) (((pt1->y+pt2->y)/2.0)); - ptAvg1.x = (nscoord) (((pt2->x+pt3->x)/2.0)); - ptAvg1.y = (nscoord) (((pt2->y+pt3->y)/2.0)); - TheSegment.SetPoints(ptAvg.x,ptAvg.y,pt2->x,pt2->y,ptAvg1.x,ptAvg1.y); - default: - break; + } + } else { + // just have one point + result = PR_FALSE; } + } else { + // all finished + result = PR_FALSE; } return result; diff --git a/gfx/src/windows/nsRenderingContextWin.cpp b/gfx/src/windows/nsRenderingContextWin.cpp index 1b7b22ad295..3baa943c6b8 100644 --- a/gfx/src/windows/nsRenderingContextWin.cpp +++ b/gfx/src/windows/nsRenderingContextWin.cpp @@ -1072,6 +1072,40 @@ NS_IMETHODIMP nsRenderingContextWin :: DrawLine(nscoord aX0, nscoord aY0, nscoor return NS_OK; } + /** --------------------------------------------------- + * See documentation in nsIRenderingContextImpl.h + * @update 5/01/00 dwc + */ +NS_IMETHODIMP nsRenderingContextWin :: DrawStdLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1) +{ + + if (nsLineStyle_kNone == mCurrLineStyle) + return NS_OK; + + SetupPen(); + + if (nsLineStyle_kDotted == mCurrLineStyle) + { + lineddastruct dda_struct; + + dda_struct.nDottedPixel = 1; + dda_struct.dc = mDC; + dda_struct.crColor = mColor; + + LineDDA((int)(aX0),(int)(aY0),(int)(aX1),(int)(aY1),(LINEDDAPROC) LineDDAFunc,(long)&dda_struct); + } + else + { + ::MoveToEx(mDC, (int)(aX0), (int)(aY0), NULL); + ::LineTo(mDC, (int)(aX1), (int)(aY1)); + } + + return NS_OK; + +} + + + NS_IMETHODIMP nsRenderingContextWin :: DrawPolyline(const nsPoint aPoints[], PRInt32 aNumPoints) { if (nsLineStyle_kNone == mCurrLineStyle) diff --git a/gfx/src/windows/nsRenderingContextWin.h b/gfx/src/windows/nsRenderingContextWin.h index 9b673d28cbf..8c1dd9da8e8 100644 --- a/gfx/src/windows/nsRenderingContextWin.h +++ b/gfx/src/windows/nsRenderingContextWin.h @@ -96,6 +96,7 @@ public: NS_IMETHOD DestroyDrawingSurface(nsDrawingSurface aDS); NS_IMETHOD DrawLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1); + NS_IMETHOD DrawStdLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1); NS_IMETHOD DrawPolyline(const nsPoint aPoints[], PRInt32 aNumPoints); NS_IMETHOD DrawRect(const nsRect& aRect); @@ -203,6 +204,8 @@ protected: */ virtual PRBool CanTile(nscoord aWidth,nscoord aHeight); + + private: // ConditionRect is used to fix a coordinate overflow problem under WIN95. void ConditionRect(nsRect aSrcRect, RECT& aDestRect);