OSDN Git Service

Change Dir Structure to be same as TortoiseSVN'
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / RevisionGraph / RevisionGraphDlgDraw.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-2008 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #include "stdafx.h"\r
20 #include "TortoiseProc.h"\r
21 #include "MyMemDC.h"\r
22 #include "Revisiongraphdlg.h"\r
23 #include "MessageBox.h"\r
24 #include "SVN.h"\r
25 #include "TempFile.h"\r
26 #include "UnicodeUtils.h"\r
27 #include "TSVNPath.h"\r
28 #include "SVNInfo.h"\r
29 #include "SVNDiff.h"\r
30 #include ".\revisiongraphwnd.h"\r
31 #include "RevisionGraph/IRevisionGraphLayout.h"\r
32 \r
33 #ifdef _DEBUG\r
34 #define new DEBUG_NEW\r
35 #undef THIS_FILE\r
36 static char THIS_FILE[] = __FILE__;\r
37 #endif\r
38 \r
39 using namespace Gdiplus;\r
40 \r
41 /************************************************************************/\r
42 /* Graphing functions                                                   */\r
43 /************************************************************************/\r
44 CFont* CRevisionGraphWnd::GetFont(BOOL bItalic /*= FALSE*/, BOOL bBold /*= FALSE*/)\r
45 {\r
46         int nIndex = 0;\r
47         if (bBold)\r
48                 nIndex |= 1;\r
49         if (bItalic)\r
50                 nIndex |= 2;\r
51         if (m_apFonts[nIndex] == NULL)\r
52         {\r
53                 m_apFonts[nIndex] = new CFont;\r
54                 m_lfBaseFont.lfWeight = bBold ? FW_BOLD : FW_NORMAL;\r
55                 m_lfBaseFont.lfItalic = (BYTE) bItalic;\r
56                 m_lfBaseFont.lfStrikeOut = (BYTE) FALSE;\r
57                 CDC * pDC = GetDC();\r
58                 m_lfBaseFont.lfHeight = -MulDiv(m_nFontSize, GetDeviceCaps(pDC->m_hDC, LOGPIXELSY), 72);\r
59                 ReleaseDC(pDC);\r
60                 // use the empty font name, so GDI takes the first font which matches\r
61                 // the specs. Maybe this will help render chinese/japanese chars correctly.\r
62                 _tcsncpy_s(m_lfBaseFont.lfFaceName, 32, _T("MS Shell Dlg 2"), 32);\r
63                 if (!m_apFonts[nIndex]->CreateFontIndirect(&m_lfBaseFont))\r
64                 {\r
65                         delete m_apFonts[nIndex];\r
66                         m_apFonts[nIndex] = NULL;\r
67                         return CWnd::GetFont();\r
68                 }\r
69         }\r
70         return m_apFonts[nIndex];\r
71 }\r
72 \r
73 BOOL CRevisionGraphWnd::OnEraseBkgnd(CDC* /*pDC*/)\r
74 {\r
75         return TRUE;\r
76 }\r
77 \r
78 void CRevisionGraphWnd::OnPaint() \r
79 {\r
80         CPaintDC dc(this); // device context for painting\r
81         CRect rect;\r
82         GetClientRect(&rect);\r
83         if (m_bThreadRunning)\r
84         {\r
85                 dc.FillSolidRect(rect, ::GetSysColor(COLOR_APPWORKSPACE));\r
86                 CWnd::OnPaint();\r
87                 return;\r
88         }\r
89     else if (m_layout.get() == NULL)\r
90         {\r
91                 CString sNoGraphText;\r
92                 sNoGraphText.LoadString(IDS_REVGRAPH_ERR_NOGRAPH);\r
93                 dc.FillSolidRect(rect, RGB(255,255,255));\r
94                 dc.ExtTextOut(20,20,ETO_CLIPPED,NULL,sNoGraphText,NULL);\r
95                 return;\r
96         }\r
97         \r
98     DrawGraph(&dc, rect, GetScrollPos(SB_VERT), GetScrollPos(SB_HORZ), false);\r
99 }\r
100 \r
101 void CRevisionGraphWnd::CutawayPoints (const RectF& rect, float cutLen, TCutRectangle& result)\r
102 {\r
103     result[0] = PointF (rect.X, rect.Y + cutLen);\r
104     result[1] = PointF (rect.X + cutLen, rect.Y);\r
105     result[2] = PointF (rect.GetRight() - cutLen, rect.Y);\r
106     result[3] = PointF (rect.GetRight(), rect.Y + cutLen);\r
107     result[4] = PointF (rect.GetRight(), rect.GetBottom() - cutLen);\r
108     result[5] = PointF (rect.GetRight() - cutLen, rect.GetBottom());\r
109     result[6] = PointF (rect.X + cutLen, rect.GetBottom());\r
110     result[7] = PointF (rect.X, rect.GetBottom() - cutLen);\r
111 }\r
112 \r
113 void CRevisionGraphWnd::DrawRoundedRect (Graphics& graphics, const Pen* pen, const Brush* brush, const RectF& rect)\r
114 {\r
115     enum {POINT_COUNT = 8};\r
116 \r
117     float radius = 16 * m_fZoomFactor;\r
118         PointF points[POINT_COUNT];\r
119     CutawayPoints (rect, radius, points);\r
120 \r
121     GraphicsPath path;\r
122     path.AddArc (points[0].X, points[1].Y, radius, radius, 180, 90);\r
123     path.AddArc (points[2].X, points[2].Y, radius, radius, 270, 90);\r
124     path.AddArc (points[5].X, points[4].Y, radius, radius, 0, 90);\r
125     path.AddArc (points[7].X, points[7].Y, radius, radius, 90, 90);\r
126 \r
127     points[0].Y -= radius / 2;\r
128     path.AddLine (points[7], points[0]);\r
129 \r
130     if (brush != NULL)\r
131         graphics.FillPath (brush, &path);\r
132     if (pen != NULL)\r
133         graphics.DrawPath (pen, &path);\r
134 }\r
135 \r
136 void CRevisionGraphWnd::DrawOctangle (Graphics& graphics, const Pen* pen, const Brush* brush, const RectF& rect)\r
137 {\r
138     enum {POINT_COUNT = 8};\r
139 \r
140         PointF points[POINT_COUNT];\r
141     CutawayPoints (rect, min (rect.Height, rect.Width) / 4, points);\r
142 \r
143     if (brush != NULL)\r
144         graphics.FillPolygon (brush, points, POINT_COUNT);\r
145     if (pen != NULL)\r
146         graphics.DrawPolygon (pen, points, POINT_COUNT);\r
147 }\r
148 \r
149 void CRevisionGraphWnd::DrawShape (Graphics& graphics, const Pen* pen, const Brush* brush, const RectF& rect, NodeShape shape)\r
150 {\r
151         switch( shape )\r
152         {\r
153         case TSVNRectangle:\r
154         if (brush != NULL)\r
155             graphics.FillRectangle (brush, rect);\r
156         if (pen != NULL)\r
157             graphics.DrawRectangle (pen, rect);\r
158                 break;\r
159         case TSVNRoundRect:\r
160                 DrawRoundedRect (graphics, pen, brush, rect);\r
161                 break;\r
162         case TSVNOctangle:\r
163                 DrawOctangle (graphics, pen, brush, rect);\r
164                 break;\r
165         case TSVNEllipse:\r
166         if (brush != NULL)\r
167             graphics.FillEllipse (brush, rect);\r
168         if (pen != NULL)\r
169             graphics.DrawEllipse(pen, rect);\r
170                 break;\r
171         default:\r
172                 ASSERT(FALSE);  //unknown type\r
173                 return;\r
174         }\r
175 }\r
176 \r
177 inline BYTE LimitedScaleColor (BYTE c1, BYTE c2, float factor)\r
178 {\r
179     BYTE scaled = c2 + (BYTE)((c1-c2)*factor);\r
180     return c1 < c2\r
181         ? max (c1, scaled)\r
182         : min (c1, scaled);\r
183 }\r
184 \r
185 Color LimitedScaleColor (const Color& c1, const Color& c2, float factor)\r
186 {\r
187     return Color ( LimitedScaleColor (c1.GetA(), c2.GetA(), factor)\r
188                  , LimitedScaleColor (c1.GetR(), c2.GetR(), factor)\r
189                  , LimitedScaleColor (c1.GetG(), c2.GetG(), factor)\r
190                  , LimitedScaleColor (c1.GetB(), c2.GetB(), factor));\r
191 }\r
192 \r
193 void CRevisionGraphWnd::DrawShadow (Graphics& graphics, const RectF& rect,\r
194                                     Color shadowColor, NodeShape shape)\r
195 {\r
196         // draw the shadow\r
197 \r
198         RectF shadow = rect;\r
199     shadow.Offset (2, 2);\r
200 \r
201     Pen pen (shadowColor);\r
202         SolidBrush brush (shadowColor);\r
203 \r
204     DrawShape (graphics, &pen, &brush, shadow, shape);\r
205 }\r
206 \r
207 void CRevisionGraphWnd::DrawNode(Graphics& graphics, const RectF& rect,\r
208                                  COLORREF contourRef, Color overlayColor, \r
209                                  const CVisibleGraphNode *node, NodeShape shape)\r
210 {\r
211     // special case: line deleted but deletion node removed\r
212 \r
213     if (   (node->GetNext() == NULL) \r
214         && (node->GetClassification().Is (CNodeClassification::PATH_ONLY_DELETED)))\r
215     {\r
216         contourRef = m_Colors.GetColor(CColors::DeletedNode);\r
217     }\r
218 \r
219     bool nodeSelected = (m_SelectedEntry1 == node) || (m_SelectedEntry2 == node);\r
220 \r
221     // calculate the RGB color values we need to draw the node\r
222 \r
223     Color contour;\r
224     contour.SetFromCOLORREF (contourRef);\r
225 \r
226     Color background;\r
227     background.SetFromCOLORREF (GetSysColor(COLOR_WINDOW));\r
228     Color textColor;\r
229     textColor.SetFromCOLORREF (GetSysColor(COLOR_WINDOWTEXT));\r
230 \r
231         Color selColor = LimitedScaleColor (background, contour, 0.5f);\r
232         Color brightColor = LimitedScaleColor (background, contour, 0.9f);\r
233 \r
234         // Draw the main shape\r
235 \r
236     bool isWorkingCopy = node->GetClassification().Is (CNodeClassification::IS_WORKINGCOPY);\r
237     Color penColor = (contour.GetValue() == Color::White) || isWorkingCopy\r
238                      ? textColor\r
239                      : contour;\r
240     Color brushColor = nodeSelected ? selColor : brightColor;\r
241 \r
242     Pen pen (penColor, isWorkingCopy ? 3.0f : 1.0f);\r
243     SolidBrush brush (brushColor);\r
244 \r
245     Pen* penRef = overlayColor.GetValue() == 0 ? &pen : NULL;\r
246     DrawShape (graphics, penRef, &brush, rect, shape);\r
247 \r
248     // overlay with some other color\r
249 \r
250     if (overlayColor.GetValue() != 0)\r
251     {\r
252         SolidBrush brush (overlayColor);\r
253         DrawShape (graphics, &pen, &brush, rect, shape);\r
254     }\r
255 }\r
256 \r
257 RectF CRevisionGraphWnd::GetNodeRect (const ILayoutNodeList::SNode& node, const CSize& offset) const\r
258 {\r
259     // get node and position\r
260 \r
261     PointF leftTop ( node.rect.left * m_fZoomFactor\r
262                    , node.rect.top * m_fZoomFactor);\r
263         RectF noderect ( leftTop.X - offset.cx\r
264                    , leftTop.Y - offset.cy\r
265                    , node.rect.right * m_fZoomFactor - leftTop.X - 1\r
266                    , node.rect.bottom * m_fZoomFactor - leftTop.Y);\r
267 \r
268     // show two separate lines for touching nodes, \r
269     // unless the scale is too small\r
270 \r
271     if (noderect.Height > 4.0f)\r
272         noderect.Height -= 1.0f;\r
273 \r
274     // done\r
275 \r
276     return noderect;\r
277 }\r
278 \r
279 void CRevisionGraphWnd::DrawShadows (Graphics& graphics, const CRect& logRect, const CSize& offset)\r
280 {\r
281     // shadow color to use\r
282 \r
283     Color background;\r
284     background.SetFromCOLORREF (GetSysColor(COLOR_WINDOW));\r
285     Color textColor;\r
286     textColor.SetFromCOLORREF (GetSysColor(COLOR_WINDOWTEXT));\r
287 \r
288     Color shadowColor = LimitedScaleColor (background, ARGB (Color::Black), 0.5f);\r
289 \r
290     // iterate over all visible nodes\r
291 \r
292     std::auto_ptr<const ILayoutNodeList> nodes (m_layout->GetNodes());\r
293     for ( index_t index = nodes->GetFirstVisible (logRect)\r
294         ; index != NO_INDEX\r
295         ; index = nodes->GetNextVisible (index, logRect))\r
296         {\r
297         // get node and position\r
298 \r
299         ILayoutNodeList::SNode node = nodes->GetNode (index);\r
300                 RectF noderect (GetNodeRect (node, offset));\r
301 \r
302         // actual drawing\r
303 \r
304                 switch (node.style)\r
305                 {\r
306                 case ILayoutNodeList::SNode::STYLE_DELETED:\r
307                 case ILayoutNodeList::SNode::STYLE_RENAMED:\r
308                         DrawShadow (graphics, noderect, shadowColor, TSVNOctangle);\r
309                         break;\r
310                 case ILayoutNodeList::SNode::STYLE_ADDED:\r
311             DrawShadow(graphics, noderect, shadowColor, TSVNRoundRect);\r
312             break;\r
313                 case ILayoutNodeList::SNode::STYLE_LAST:\r
314                         DrawShadow(graphics, noderect, shadowColor, TSVNEllipse);\r
315                         break;\r
316                 default:\r
317             DrawShadow(graphics, noderect, shadowColor, TSVNRectangle);\r
318                         break;\r
319                 }\r
320     }\r
321 }\r
322 \r
323 void CRevisionGraphWnd::DrawNodes (Graphics& graphics, const CRect& logRect, const CSize& offset)\r
324 {\r
325     // iterate over all visible nodes\r
326 \r
327     std::auto_ptr<const ILayoutNodeList> nodes (m_layout->GetNodes());\r
328     for ( index_t index = nodes->GetFirstVisible (logRect)\r
329         ; index != NO_INDEX\r
330         ; index = nodes->GetNextVisible (index, logRect))\r
331         {\r
332         // get node and position\r
333 \r
334         ILayoutNodeList::SNode node = nodes->GetNode (index);\r
335                 RectF noderect (GetNodeRect (node, offset));\r
336 \r
337         // actual drawing\r
338 \r
339         Color transparent (0);\r
340         Color overlayColor = transparent;\r
341 \r
342                 switch (node.style)\r
343                 {\r
344                 case ILayoutNodeList::SNode::STYLE_DELETED:\r
345                         DrawNode(graphics, noderect, m_Colors.GetColor(CColors::DeletedNode), transparent, node.node, TSVNOctangle);\r
346                         break;\r
347 \r
348         case ILayoutNodeList::SNode::STYLE_ADDED:\r
349             if (m_bTweakTagsColors && node.node->GetClassification().Is (CNodeClassification::IS_TAG))\r
350                 overlayColor = Color (128, 250, 250, 92);\r
351             else if (m_bTweakTrunkColors && node.node->GetClassification().Is (CNodeClassification::IS_TRUNK))\r
352                 overlayColor = Color (64, 64, 255, 64);\r
353             DrawNode(graphics, noderect, m_Colors.GetColor(CColors::AddedNode), overlayColor, node.node, TSVNRoundRect);\r
354             break;\r
355 \r
356         case ILayoutNodeList::SNode::STYLE_RENAMED:\r
357             if (m_bTweakTagsColors && node.node->GetClassification().Is (CNodeClassification::IS_TAG))\r
358                 overlayColor = Color (128, 92, 160, 160);\r
359             else if (m_bTweakTrunkColors && node.node->GetClassification().Is (CNodeClassification::IS_TRUNK))\r
360                 overlayColor = Color (64, 0, 255, 160);\r
361             DrawNode(graphics, noderect, m_Colors.GetColor(CColors::RenamedNode), overlayColor, node.node, TSVNOctangle);\r
362                         break;\r
363 \r
364         case ILayoutNodeList::SNode::STYLE_LAST:\r
365                         DrawNode(graphics, noderect, m_Colors.GetColor(CColors::LastCommitNode), transparent, node.node, TSVNEllipse);\r
366                         break;\r
367 \r
368         case ILayoutNodeList::SNode::STYLE_MODIFIED:\r
369                         DrawNode(graphics, noderect, GetSysColor(COLOR_WINDOWTEXT), transparent, node.node, TSVNRectangle);\r
370                         break;\r
371 \r
372         default:\r
373             DrawNode(graphics, noderect, GetSysColor(COLOR_WINDOW), transparent, node.node, TSVNRectangle);\r
374                         break;\r
375                 }\r
376 \r
377         // Draw the "tagged" icon\r
378 \r
379         if (node.node->GetFirstTag() != NULL)\r
380                 {\r
381                         // draw the icon\r
382             float squareSize = 16 * m_fZoomFactor;\r
383             float squareDist = min ( (noderect.Height - squareSize) / 2\r
384                                    , squareSize / 2);\r
385 \r
386             PointF leftTop (noderect.GetRight() - squareSize * 3 / 2, noderect.Y + squareDist);\r
387             PointF leftBottom (leftTop.X, leftTop.Y + squareSize);\r
388             RectF square (leftTop, SizeF (squareSize, squareSize));\r
389 \r
390             Pen pen (Color(128, 0, 0, 0));\r
391             LinearGradientBrush lgBrush (leftTop, leftBottom, Color (250, 250, 92), Color (230, 230, 64));\r
392             graphics.FillRectangle (&lgBrush, square);\r
393             graphics.DrawRectangle (&pen, square);\r
394                 }\r
395     }\r
396 }\r
397 \r
398 void CRevisionGraphWnd::DrawConnections (CDC* pDC, const CRect& logRect, const CSize& offset)\r
399 {\r
400     enum {MAX_POINTS = 100};\r
401     CPoint points[MAX_POINTS];\r
402 \r
403         CPen newpen(PS_SOLID, 0, GetSysColor(COLOR_WINDOWTEXT));\r
404         CPen * pOldPen = pDC->SelectObject(&newpen);\r
405 \r
406     // iterate over all visible lines\r
407 \r
408     std::auto_ptr<const ILayoutConnectionList> connections (m_layout->GetConnections());\r
409     for ( index_t index = connections->GetFirstVisible (logRect)\r
410         ; index != NO_INDEX\r
411         ; index = connections->GetNextVisible (index, logRect))\r
412         {\r
413         // get connection and point position\r
414 \r
415         ILayoutConnectionList::SConnection connection \r
416             = connections->GetConnection (index);\r
417 \r
418         if (connection.numberOfPoints > MAX_POINTS)\r
419             continue;\r
420 \r
421         for (index_t i = 0; i < connection.numberOfPoints; ++i)\r
422         {\r
423             points[i].x = (int)(connection.points[i].x * m_fZoomFactor) - offset.cx;\r
424             points[i].y = (int)(connection.points[i].y * m_fZoomFactor) - offset.cy;\r
425         }\r
426 \r
427                 // draw the connection\r
428 \r
429                 pDC->PolyBezier (points, connection.numberOfPoints);\r
430         }\r
431 \r
432         pDC->SelectObject(pOldPen);\r
433 }\r
434 \r
435 void CRevisionGraphWnd::DrawTexts (CDC* pDC, const CRect& logRect, const CSize& offset)\r
436 {\r
437         COLORREF textcolor = GetSysColor(COLOR_WINDOWTEXT);\r
438     if (m_nFontSize <= 0)\r
439         return;\r
440 \r
441     // iterate over all visible nodes\r
442 \r
443     pDC->SetTextAlign (TA_CENTER | TA_TOP);\r
444     std::auto_ptr<const ILayoutTextList> texts (m_layout->GetTexts());\r
445     for ( index_t index = texts->GetFirstVisible (logRect)\r
446         ; index != NO_INDEX\r
447         ; index = texts->GetNextVisible (index, logRect))\r
448         {\r
449         // get node and position\r
450 \r
451         ILayoutTextList::SText text = texts->GetText (index);\r
452                 CRect textRect ( (int)(text.rect.left * m_fZoomFactor) - offset.cx\r
453                        , (int)(text.rect.top * m_fZoomFactor) - offset.cy\r
454                        , (int)(text.rect.right * m_fZoomFactor) - offset.cx\r
455                        , (int)(text.rect.bottom * m_fZoomFactor) - offset.cy);\r
456 \r
457                 // draw the revision text\r
458 \r
459                 pDC->SetTextColor (textcolor);\r
460         pDC->SelectObject (GetFont (FALSE, text.style));\r
461         pDC->ExtTextOut ((textRect.left + textRect.right)/2, textRect.top, 0, &textRect, text.text, NULL);\r
462     }\r
463 }\r
464 \r
465 void CRevisionGraphWnd::DrawGraph(CDC* pDC, const CRect& rect, int nVScrollPos, int nHScrollPos, bool bDirectDraw)\r
466 {\r
467         CDC * memDC = bDirectDraw\r
468                 ? pDC\r
469                 : new CMyMemDC(pDC);\r
470         \r
471         memDC->FillSolidRect(rect, GetSysColor(COLOR_WINDOW));\r
472         memDC->SetBkMode(TRANSPARENT);\r
473 \r
474     // transform visible\r
475 \r
476     CSize offset (nHScrollPos, nVScrollPos);\r
477     CRect logRect ( (int)(offset.cx / m_fZoomFactor)-1\r
478                   , (int)(offset.cy / m_fZoomFactor)-1\r
479                   , (int)((rect.Width() + offset.cx) / m_fZoomFactor) + 1\r
480                   , (int)((rect.Height() + offset.cy) / m_fZoomFactor) + 1);\r
481 \r
482     // draw the different components\r
483 \r
484     Graphics graphics (*memDC);\r
485     graphics.SetPageUnit (UnitPixel);\r
486 \r
487         if (m_fZoomFactor > 0.2f)\r
488         DrawShadows (graphics, logRect, offset);\r
489 \r
490     DrawNodes (graphics, logRect, offset);\r
491     DrawConnections (memDC, logRect, offset);\r
492     DrawTexts (memDC, logRect, offset);\r
493 \r
494         // find out which nodes are in the visible area of the client rect\r
495 \r
496         if ((!bDirectDraw)&&(m_Preview.GetSafeHandle())&&(m_bShowOverview))\r
497         {\r
498                 // draw the overview image rectangle in the top right corner\r
499                 CMyMemDC memDC2(memDC, true);\r
500                 memDC2.SetWindowOrg(0, 0);\r
501                 HBITMAP oldhbm = (HBITMAP)memDC2.SelectObject(&m_Preview);\r
502                 memDC->BitBlt(rect.Width()-m_previewWidth, 0, m_previewWidth, m_previewHeight, \r
503                         &memDC2, 0, 0, SRCCOPY);\r
504                 memDC2.SelectObject(oldhbm);\r
505                 // draw the border for the overview rectangle\r
506                 m_OverviewRect.left = rect.Width()-m_previewWidth;\r
507                 m_OverviewRect.top = 0;\r
508                 m_OverviewRect.right = rect.Width();\r
509                 m_OverviewRect.bottom = m_previewHeight;\r
510                 memDC->DrawEdge(&m_OverviewRect, EDGE_BUMP, BF_RECT);\r
511                 // now draw a rectangle where the current view is located in the overview\r
512 \r
513         CRect viewRect = GetViewRect();\r
514         LONG width = (long)(rect.Width() * m_previewZoom / m_fZoomFactor);\r
515         LONG height = (long)(rect.Height() * m_previewZoom / m_fZoomFactor);\r
516                 LONG xpos = (long)(nHScrollPos * m_previewZoom / m_fZoomFactor);\r
517                 LONG ypos = (long)(nVScrollPos * m_previewZoom / m_fZoomFactor);\r
518                 RECT tempRect;\r
519                 tempRect.left = rect.Width()-m_previewWidth+xpos;\r
520                 tempRect.top = ypos;\r
521                 tempRect.right = tempRect.left + width;\r
522                 tempRect.bottom = tempRect.top + height;\r
523                 // make sure the position rect is not bigger than the preview window itself\r
524                 ::IntersectRect(&m_OverviewPosRect, &m_OverviewRect, &tempRect);\r
525 \r
526         RectF rect ( (float)m_OverviewPosRect.left, (float)m_OverviewPosRect.top\r
527                    , (float)m_OverviewPosRect.Width(), (float)m_OverviewPosRect.Height());\r
528         SolidBrush brush (Color (64, 0, 0, 0));\r
529         graphics.FillRectangle (&brush, rect);\r
530                 memDC->DrawEdge(&m_OverviewPosRect, EDGE_BUMP, BF_RECT);\r
531         }\r
532 \r
533         if (!bDirectDraw)\r
534                 delete memDC;\r
535 }\r
536 \r
537 void CRevisionGraphWnd::DrawRubberBand()\r
538 {\r
539         CDC * pDC = GetDC();\r
540         pDC->SetROP2(R2_NOT);\r
541         pDC->SelectObject(GetStockObject(NULL_BRUSH));\r
542         pDC->Rectangle(min(m_ptRubberStart.x, m_ptRubberEnd.x), min(m_ptRubberStart.y, m_ptRubberEnd.y), \r
543                 max(m_ptRubberStart.x, m_ptRubberEnd.x), max(m_ptRubberStart.y, m_ptRubberEnd.y));\r
544         ReleaseDC(pDC);\r
545 }\r
546 \r