X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/655719367ac5e131d9642e5783f3ecf64d1a3385..ebc0b1555201fe4f09a9d5b8b763cd816202b206:/src/common/dcbase.cpp diff --git a/src/common/dcbase.cpp b/src/common/dcbase.cpp index c683ff4f58..ecc6e00e4c 100644 --- a/src/common/dcbase.cpp +++ b/src/common/dcbase.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: common/dcbase.cpp +// Name: src/common/dcbase.cpp // Purpose: generic methods of the wxDC Class // Author: Vadim Zeitlin // Modified by: @@ -13,10 +13,6 @@ // declarations // ============================================================================ -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "dcbase.h" -#endif - // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- @@ -29,15 +25,33 @@ #endif #include "wx/dc.h" +#include "wx/dcbuffer.h" // for IMPLEMENT_DYNAMIC_CLASS -#include +#ifndef WX_PRECOMP + #include "wx/math.h" +#endif -// bool wxDCBase::sm_cacheing = FALSE; +// bool wxDCBase::sm_cacheing = false; + +IMPLEMENT_ABSTRACT_CLASS(wxDCBase, wxObject) // ============================================================================ // implementation // ============================================================================ +IMPLEMENT_DYNAMIC_CLASS(wxBufferedDC, wxMemoryDC) +IMPLEMENT_ABSTRACT_CLASS(wxBufferedPaintDC, wxBufferedDC) + +#if WXWIN_COMPATIBILITY_2_6 +void wxDCBase::BeginDrawing() +{ +} + +void wxDCBase::EndDrawing() +{ +} +#endif // WXWIN_COMPATIBILITY_2_6 + // ---------------------------------------------------------------------------- // special symbols // ---------------------------------------------------------------------------- @@ -50,8 +64,9 @@ void wxDCBase::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord x2 = x1 + width, y2 = y1 + height; - // this is to yield width of 3 for width == height == 10 - SetPen(wxPen(GetTextForeground(), (width + height + 1) / 7, wxSOLID)); + // the pen width is calibrated to give 3 for width == height == 10 + wxDCPenChanger pen((wxDC&)*this, + wxPen(GetTextForeground(), (width + height + 1)/7)); // we're drawing a scaled version of wx/generic/tick.xpm here wxCoord x3 = x1 + (4*width) / 10, // x of the tick bottom @@ -63,6 +78,42 @@ void wxDCBase::DoDrawCheckMark(wxCoord x1, wxCoord y1, CalcBoundingBox(x2, y2); } +// ---------------------------------------------------------------------------- +// stubs for functions not implemented in all ports +// ---------------------------------------------------------------------------- + +bool +wxDCBase::DoStretchBlit(wxCoord xdest, wxCoord ydest, + wxCoord dstWidth, wxCoord dstHeight, + wxDC *source, + wxCoord xsrc, wxCoord ysrc, + wxCoord srcWidth, wxCoord srcHeight, + int rop, + bool useMask, + wxCoord xsrcMask, + wxCoord ysrcMask) +{ + wxCHECK_MSG( srcWidth && srcHeight && dstWidth && dstHeight, false, + _T("invalid blit size") ); + + // emulate the stretching by modifying the DC scale + double xscale = (double)srcWidth/dstWidth, + yscale = (double)srcHeight/dstHeight; + + double xscaleOld, yscaleOld; + GetUserScale(&xscaleOld, &yscaleOld); + SetUserScale(xscaleOld/xscale, yscaleOld/yscale); + + bool rc = DoBlit(wxCoord(xdest*xscale), wxCoord(ydest*yscale), + wxCoord(dstWidth*xscale), wxCoord(dstHeight*yscale), + source, + xsrc, ysrc, rop, useMask, xsrcMask, ysrcMask); + + SetUserScale(xscaleOld, yscaleOld); + + return rc; +} + // ---------------------------------------------------------------------------- // line/polygons // ---------------------------------------------------------------------------- @@ -291,7 +342,7 @@ static bool wx_spline_add_point(double x, double y) point->x = (int) x; point->y = (int) y; wx_spline_point_list.Append((wxObject*)point); - return TRUE; + return true; } static void wx_spline_draw_point_array(wxDCBase *dc) @@ -316,6 +367,10 @@ void wxDCBase::DoDrawSpline( wxList *points ) double x1, y1, x2, y2; wxList::compatibility_iterator node = points->GetFirst(); + if (!node) + // empty list + return; + p = (wxPoint *)node->GetData(); x1 = p->x; @@ -371,12 +426,12 @@ void wxDCBase::DoDrawSpline( wxList *points ) // Each element of the widths array will be the width of the string up to and -// including the coresoponding character in text. This is the generic +// including the corresponding character in text. This is the generic // implementation, the port-specific classes should do this with native APIs // if available and if faster. Note: pango_layout_index_to_pos is much slower // than calling GetTextExtent!! -#define FWC_SIZE 128 +#define FWC_SIZE 256 class FontWidthCache { @@ -403,15 +458,14 @@ bool wxDCBase::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) { int totalWidth = 0; - size_t i, len = text.Length(); + const size_t len = text.length(); widths.Empty(); widths.Add(0, len); - int w, h; // reset the cache if font or horizontal scale have changed - if (!s_fontWidthCache.m_widths || - (s_fontWidthCache.m_scaleX != m_scaleX) || - (s_fontWidthCache.m_font != GetFont())) + if ( !s_fontWidthCache.m_widths || + !wxIsSameDouble(s_fontWidthCache.m_scaleX, m_scaleX) || + (s_fontWidthCache.m_font != GetFont()) ) { s_fontWidthCache.Reset(); s_fontWidthCache.m_font = GetFont(); @@ -420,7 +474,8 @@ bool wxDCBase::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) // Calculate the position of each character based on the widths of // the previous characters - for (i=0; i= xDelta) + { + x -= xDelta; + if (nR1 > nR2) + nR = nR1 - (nR1-nR2)*(w-x)/w; + else + nR = nR1 + (nR2-nR1)*(w-x)/w; + + if (nG1 > nG2) + nG = nG1 - (nG1-nG2)*(w-x)/w; + else + nG = nG1 + (nG2-nG1)*(w-x)/w; + + if (nB1 > nB2) + nB = nB1 - (nB1-nB2)*(w-x)/w; + else + nB = nB1 + (nB2-nB1)*(w-x)/w; + + wxColour colour(nR,nG,nB); + SetPen(wxPen(colour, 1, wxSOLID)); + SetBrush(wxBrush(colour)); + if(nDirection == wxEAST) + DrawRectangle(rect.GetRight()-x-xDelta, rect.GetTop(), + xDelta, rect.GetHeight()); + else //nDirection == wxWEST + DrawRectangle(rect.GetLeft()+x, rect.GetTop(), + xDelta, rect.GetHeight()); + } + } + else // nDirection == wxNORTH || nDirection == wxSOUTH + { + wxInt32 y = rect.GetHeight(); + wxInt32 w = y; // height of area to shade + wxInt32 yDelta = w/255; // height of one shade bend + if (yDelta < 1) + yDelta = 1; + + while (y > 0) + { + y -= yDelta; + if (nR1 > nR2) + nR = nR1 - (nR1-nR2)*(w-y)/w; + else + nR = nR1 + (nR2-nR1)*(w-y)/w; + + if (nG1 > nG2) + nG = nG1 - (nG1-nG2)*(w-y)/w; + else + nG = nG1 + (nG2-nG1)*(w-y)/w; + + if (nB1 > nB2) + nB = nB1 - (nB1-nB2)*(w-y)/w; + else + nB = nB1 + (nB2-nB1)*(w-y)/w; + + wxColour colour(nR,nG,nB); + SetPen(wxPen(colour, 1, wxSOLID)); + SetBrush(wxBrush(colour)); + if(nDirection == wxNORTH) + DrawRectangle(rect.GetLeft(), rect.GetTop()+y, + rect.GetWidth(), yDelta); + else //nDirection == wxSOUTH + DrawRectangle(rect.GetLeft(), rect.GetBottom()-y-yDelta, + rect.GetWidth(), yDelta); + } + } + + SetPen(oldPen); + SetBrush(oldBrush); +} + +void wxDCBase::DoGradientFillConcentric(const wxRect& rect, + const wxColour& initialColour, + const wxColour& destColour, + const wxPoint& circleCenter) +{ + //save the old pen color + wxColour oldPenColour = m_pen.GetColour(); + + wxUint8 nR1 = destColour.Red(); + wxUint8 nG1 = destColour.Green(); + wxUint8 nB1 = destColour.Blue(); + wxUint8 nR2 = initialColour.Red(); + wxUint8 nG2 = initialColour.Green(); + wxUint8 nB2 = initialColour.Blue(); + wxUint8 nR, nG, nB; + + + //Radius + wxInt32 cx = rect.GetWidth() / 2; + wxInt32 cy = rect.GetHeight() / 2; + wxInt32 nRadius; + if (cx < cy) + nRadius = cx; + else + nRadius = cy; + + //Offset of circle + wxInt32 nCircleOffX = circleCenter.x - (rect.GetWidth() / 2); + wxInt32 nCircleOffY = circleCenter.y - (rect.GetHeight() / 2); + + for ( wxInt32 x = 0; x < rect.GetWidth(); x++ ) + { + for ( wxInt32 y = 0; y < rect.GetHeight(); y++ ) + { + //get color difference + wxInt32 nGradient = ((nRadius - + (wxInt32)sqrt( + pow((double)(x - cx - nCircleOffX), 2) + + pow((double)(y - cy - nCircleOffY), 2) + )) * 100) / nRadius; + + //normalize Gradient + if (nGradient < 0 ) + nGradient = 0; + + //get dest colors + nR = (wxUint8)(nR1 + ((nR2 - nR1) * nGradient / 100)); + nG = (wxUint8)(nG1 + ((nG2 - nG1) * nGradient / 100)); + nB = (wxUint8)(nB1 + ((nB2 - nB1) * nGradient / 100)); + + //set the pixel + m_pen.SetColour(wxColour(nR,nG,nB)); + DrawPoint(wxPoint(x + rect.GetLeft(), y + rect.GetTop())); + } + } + //return old pen color + m_pen.SetColour(oldPenColour); +} + /* Notes for wxWidgets DrawEllipticArcRot(...) @@ -726,13 +937,13 @@ void wxDCBase::DoDrawEllipticArcRot( wxCoord x, wxCoord y, list.Append( (wxObject*) new wxPoint( x+w/2, y+h/2 ) ); // copy list into array and delete list elements - int n = list.Number(); + int n = list.GetCount(); wxPoint *points = new wxPoint[n]; int i = 0; wxNode* node = 0; - for ( node = list.First(); node; node = node->Next(), i++ ) + for ( node = list.GetFirst(); node; node = node->GetNext(), i++ ) { - wxPoint *point = (wxPoint *)node->Data(); + wxPoint *point = (wxPoint *)node->GetData(); points[i].x = point->x; points[i].y = point->y; delete point; @@ -762,12 +973,12 @@ void wxDCBase::Rotate( wxList* points, double angle, wxPoint center ) { if( angle != 0.0 ) { - double pi(3.1415926536); + double pi(M_PI); double dSinA = -sin(angle*2.0*pi/360.0); double dCosA = cos(angle*2.0*pi/360.0); - for ( wxNode* node = points->First(); node; node = node->Next() ) + for ( wxNode* node = points->GetFirst(); node; node = node->GetNext() ) { - wxPoint* point = (wxPoint*)node->Data(); + wxPoint* point = (wxPoint*)node->GetData(); // transform coordinates, if necessary if( center.x ) point->x -= center.x; @@ -790,7 +1001,7 @@ void wxDCBase::CalculateEllipticPoints( wxList* points, wxCoord w, wxCoord h, double sa, double ea ) { - double pi = 3.1415926535; + double pi = M_PI; double sar = 0; double ear = 0; int xsa = 0; @@ -903,14 +1114,14 @@ void wxDCBase::CalculateEllipticPoints( wxList* points, bool bForceTurn = ( sq == eq && sa > ea ); while( !bReady ) { - for( wxNode *node = pointsarray[q].First(); node; node = node->Next() ) + for( wxNode *node = pointsarray[q].GetFirst(); node; node = node->GetNext() ) { // once: go to starting point in start quadrant if( !bStarted && ( - ( (wxPoint*) node->Data() )->x < xsa+1 && q <= 1 + ( (wxPoint*) node->GetData() )->x < xsa+1 && q <= 1 || - ( (wxPoint*) node->Data() )->x > xsa-1 && q >= 2 + ( (wxPoint*) node->GetData() )->x > xsa-1 && q >= 2 ) ) { @@ -922,16 +1133,16 @@ void wxDCBase::CalculateEllipticPoints( wxList* points, { if( q != eq || bForceTurn || - ( (wxPoint*) node->Data() )->x > xea+1 && q <= 1 + ( (wxPoint*) node->GetData() )->x > xea+1 && q <= 1 || - ( (wxPoint*) node->Data() )->x < xea-1 && q >= 2 + ( (wxPoint*) node->GetData() )->x < xea-1 && q >= 2 ) { // copy point - wxPoint* pPoint = new wxPoint( *((wxPoint*) node->Data() ) ); + wxPoint* pPoint = new wxPoint( *((wxPoint*) node->GetData() ) ); points->Append( (wxObject*) pPoint ); } - else if( q == eq && !bForceTurn || ( (wxPoint*) node->Data() )->x == xea) + else if( q == eq && !bForceTurn || ( (wxPoint*) node->GetData() )->x == xea) { bReady = true; } @@ -947,38 +1158,38 @@ void wxDCBase::CalculateEllipticPoints( wxList* points, // delete points for( q = 0; q < 4; ++q ) { - for( wxNode *node = pointsarray[q].First(); node; node = node->Next() ) + for( wxNode *node = pointsarray[q].GetFirst(); node; node = node->GetNext() ) { - wxPoint *p = (wxPoint *)node->Data(); + wxPoint *p = (wxPoint *)node->GetData(); delete p; } } } else { + wxNode* node; // copy whole ellipse, wxPoints will be deleted outside - for( wxNode *node = pointsarray[0].First(); node; node = node->Next() ) + for( node = pointsarray[0].GetFirst(); node; node = node->GetNext() ) { - wxObject *p = node->Data(); + wxObject *p = node->GetData(); points->Append( p ); } - for( node = pointsarray[1].First(); node; node = node->Next() ) + for( node = pointsarray[1].GetFirst(); node; node = node->GetNext() ) { - wxObject *p = node->Data(); + wxObject *p = node->GetData(); points->Append( p ); } - for( node = pointsarray[2].First(); node; node = node->Next() ) + for( node = pointsarray[2].GetFirst(); node; node = node->GetNext() ) { - wxObject *p = node->Data(); + wxObject *p = node->GetData(); points->Append( p ); } - for( node = pointsarray[3].First(); node; node = node->Next() ) + for( node = pointsarray[3].GetFirst(); node; node = node->GetNext() ) { - wxObject *p = node->Data(); + wxObject *p = node->GetData(); points->Append( p ); } } // not iUseAngles } // CalculateEllipticPoints -#endif - +#endif // __WXWINCE__