GME  13
GraphicsUtil.cpp
Go to the documentation of this file.
00001 #include "stdafx.h"
00002 
00003 #include "GMEstd.h"
00004 #include "GraphicsUtil.h"
00005 #define _USE_MATH_DEFINES
00006 #include <math.h>
00007 
00008 
00009 static bool fontBoldness[GME_FONT_KIND_NUM]             = { false, false, false };
00010 static bool fontSemiboldness[GME_FONT_KIND_NUM] = { true, true, false };
00011 static int  fontSizes[GME_FONT_KIND_NUM]                = { 16, 15, 12 };
00012 
00013 
00015 
00016 CArrowHead::CArrowHead(int dir, const std::vector<CPoint>& coords)
00017 {
00018         this->dir = dir;
00019         ASSERT(coords.size() > 0);
00020         std::vector<CPoint>::const_iterator ii = coords.begin();
00021         while(ii != coords.end()) {
00022                 CPoint coord;
00023                 switch(dir) {
00024                 case GME_RIGHT_DIRECTION:
00025                         coord.x = (*ii).x;
00026                         coord.y = (*ii).y;
00027                         break;
00028                 case GME_LEFT_DIRECTION:
00029                         coord.x = -(*ii).x;
00030                         coord.y = -(*ii).y;
00031                         break;
00032                 case GME_UP_DIRECTION:
00033                         coord.x = (*ii).y;
00034                         coord.y = -(*ii).x;
00035                         break;
00036                 case GME_DOWN_DIRECTION:
00037                         coord.x = -(*ii).y;
00038                         coord.y = (*ii).x;
00039                         break;
00040                 default:
00041                         ASSERT(false);
00042                         break;
00043                 }
00044                 path.push_back(coord);
00045                 ++ii;
00046         }
00047 }
00048 
00049 CArrowHead::~CArrowHead()
00050 {
00051 }
00052 
00053 CRect CArrowHead::GetLineCoords(long index1, long index2, double angle, bool skew)
00054 {
00055         CRect line;
00056         if (!skew) {
00057                 line.left       = path[index1].x;
00058                 line.top        = path[index1].y;
00059                 line.right      = path[index2].x;
00060                 line.bottom     = path[index2].y;
00061         } else {
00062                 line.left       = (int)(cos(angle) * path[index1].x - sin(angle) * path[index1].y + 0.5);
00063                 line.top        = (int)(sin(angle) * path[index1].x + cos(angle) * path[index1].y + 0.5);
00064                 line.right      = (int)(cos(angle) * path[index2].x - sin(angle) * path[index2].y + 0.5);
00065                 line.bottom     = (int)(sin(angle) * path[index2].x + cos(angle) * path[index2].y + 0.5);
00066         }
00067         return line;
00068 }
00069 
00070 void CArrowHead::Draw(Gdiplus::Graphics* gdip, Gdiplus::Pen* pen, Gdiplus::Brush* brush, const CPoint& tip, bool bPen,
00071                                           double angle, bool bold)
00072 {
00073         bool skew = (abs(angle) > 1.0e-6);
00074         Gdiplus::GraphicsPath arrowHeadPath;
00075         int segments = path.size();
00076         long lastx;
00077         long lasty;
00078         for (int i = 1; i < segments; i++) {
00079                 CRect line = GetLineCoords(i - 1, i, angle, skew);
00080                 arrowHeadPath.AddLine(line.left + tip.x, line.top + tip.y, line.right + tip.x, line.bottom + tip.y);
00081                 lastx = line.left + tip.x;
00082                 lasty = line.top + tip.y;
00083         }
00084 
00085         if (bold && !bPen)
00086         {
00087                 if (dir == GME_LEFT_DIRECTION || dir == GME_RIGHT_DIRECTION)
00088                 {
00089                         Gdiplus::Matrix matrix(1.0f, 0.0f, 0.0f, 1.7f, 0, (Gdiplus::REAL)-lasty * (1.7 - 1));
00090                         arrowHeadPath.Transform(&matrix);
00091                 }
00092                 else
00093                 {
00094                         Gdiplus::Matrix matrix(1.7f, 0.0f, 0.0f, 1.0f, (Gdiplus::REAL)-lastx * (1.7 - 1), 0);
00095                         arrowHeadPath.Transform(&matrix);
00096                 }
00097         }
00098         gdip->FillPath(brush, &arrowHeadPath);
00099 
00100         if (bPen) {
00101                 std::vector<Gdiplus::Point> points;
00102                 points.reserve(path.size() + 2);
00103                 for (int i = 0; i < path.size(); i++) {
00104                         points.push_back(Gdiplus::Point((int)path[i].x + tip.x, (int)path[i].y + tip.y));
00105                 }
00106                 CRect line = GetLineCoords(segments - 1, 0, angle, skew);
00107                 points.push_back(Gdiplus::Point((int)path[0].x + tip.x, (int)path[0].y + tip.y));
00108                 points.push_back(Gdiplus::Point((int)path[1].x + tip.x, (int)path[1].y + tip.y)); // <- extra point gives nice sharp corner, instead of butt-end
00109                 if (bold)
00110                 {
00111                         pen = pen->Clone();
00112                         Gdiplus::Matrix mat(3.0, 0.0, 0.0, 3.0, 0, 0);
00113                         pen->MultiplyTransform(&mat); // FIXME only shows up at higher zoom for some reason
00114                 }
00115                 gdip->DrawLines(pen, &points[0], points.size());
00116                 if (bold)
00117                 {
00118                         delete pen;
00119                 }
00120         }
00121 
00122 }
00123 
00124 
00126 
00127 CBulletArrowHead::CBulletArrowHead(int dir, const std::vector<CPoint>& coords):
00128         CArrowHead(dir, coords)
00129 {
00130 }
00131 
00132 CBulletArrowHead::~CBulletArrowHead()
00133 {
00134 }
00135 
00136 void CBulletArrowHead::Draw(Gdiplus::Graphics* gdip, Gdiplus::Pen* pen, Gdiplus::Brush* brush, const CPoint& tip, bool bPen,
00137                                                         double angle, bool bold)
00138 {
00139         ASSERT(path.size() == 2);
00140         int ox = 0;
00141         int oy = 0;
00142         if (abs(angle) < 1.0e-6)
00143         {
00144                 ox = path[0].x;
00145                 oy = path[0].y;
00146         }
00147         else    // skew
00148         {
00149                 ox = (int)(cos(angle) * path[0].x - sin(angle) * path[0].y + 0.5);
00150                 oy = (int)(sin(angle) * path[0].x + cos(angle) * path[0].y + 0.5);
00151         }
00152         int a = abs(path[1].x);
00153         int b = abs(path[1].y);
00154         Gdiplus::GraphicsPath* bulletPath = new Gdiplus::GraphicsPath();
00155         bulletPath->AddEllipse(ox - a + tip.x, oy - b + tip.y, 2 * a, 2 * b);
00156         gdip->FillPath(brush, bulletPath);
00157         gdip->DrawPath(pen, bulletPath);
00158         delete bulletPath;
00159 }
00160 
00161 
00163 
00164 CGraphics::CGraphics()
00165 {
00166 }
00167 
00168 CGraphics::~CGraphics()
00169 {
00170 }
00171 
00172 void CGraphics::Initialize(void)
00173 {
00174         CreateFonts(normalFonts,        normalGdipFonts,        FW_LIGHT);
00175         CreateFonts(semiboldFonts,      semiboldGdipFonts,      FW_NORMAL);
00176         CreateFonts(boldFonts,          boldGdipFonts,          FW_SEMIBOLD);
00177 
00178         std::vector<CPoint> arrowCoords;
00179         arrowCoords.push_back(CPoint(-5, 0));
00180         arrowCoords.push_back(CPoint(-7, -3));
00181         arrowCoords.push_back(CPoint(-1, 0));
00182         arrowCoords.push_back(CPoint(-7, 3));
00183         std::vector<CPoint> leftHalfCoords;
00184         leftHalfCoords.push_back(CPoint(-1, 0));
00185         leftHalfCoords.push_back(CPoint(-10, -5));
00186         std::vector<CPoint> rightHalfCoords;
00187         rightHalfCoords.push_back(CPoint(-1, 0));
00188         rightHalfCoords.push_back(CPoint(-10, 5));
00189         std::vector<CPoint> diamondCoords;
00190         diamondCoords.push_back(CPoint(-10, 0));
00191         diamondCoords.push_back(CPoint(-5, -3));
00192         diamondCoords.push_back(CPoint(-0, 0));
00193         diamondCoords.push_back(CPoint(-5, 3));
00194         std::vector<CPoint> apexCoords;
00195         apexCoords.push_back(CPoint(-9, -5));
00196         apexCoords.push_back(CPoint(-9, 5));
00197         apexCoords.push_back(CPoint(-1, 0));
00198         std::vector<CPoint> bulletCoords;               // Special:
00199         bulletCoords.push_back(CPoint(-4, 0));  // ellipse origo
00200         bulletCoords.push_back(CPoint(3, 3));   // a and b radius of ellipse
00201 
00202         for(int i = 0; i < GME_DIRECTION_NUM; i++) {
00203                 arrows[i]                       = new CArrowHead( i, arrowCoords );
00204                 diamonds[i]                     = new CArrowHead( i, diamondCoords );
00205                 apexes[i]                       = new CArrowHead( i, apexCoords );
00206                 bullets[i]                      = new CBulletArrowHead( i, bulletCoords );
00207                 leftHalfArrows[i]       = new CArrowHead( i, leftHalfCoords );
00208                 rightHalfArrows[i]      = new CArrowHead( i, rightHalfCoords );
00209         }
00210 }
00211 
00212 void CGraphics::Uninitialize(void)
00213 {
00214         for (std::map<CString,Gdiplus::Pen*>::iterator it = m_mapGdipPens.begin() ; it != m_mapGdipPens.end() ; ++it)
00215                 delete it->second;
00216         DeleteBrushes(gdipBrushes);
00217 
00218         for (int i = 0; i < GME_FONT_KIND_NUM; i++) {
00219                 delete normalFonts[i];
00220                 delete semiboldFonts[i];
00221                 delete boldFonts[i];
00222                 delete normalGdipFonts[i];
00223                 delete semiboldGdipFonts[i];
00224                 delete boldGdipFonts[i];
00225         }
00226 
00227         for (int i = 0; i < GME_DIRECTION_NUM; i++) {
00228                 delete arrows[i];
00229                 delete diamonds[i];
00230                 delete apexes[i];
00231                 delete bullets[i];
00232                 delete leftHalfArrows[i];
00233                 delete rightHalfArrows[i];
00234         }
00235 }
00236 
00237 void CGraphics::DeleteBrushes(GdipBrushTable& gdipBrushTable)
00238 {
00239         POSITION pos = gdipBrushTable.GetStartPosition();
00240         void* pt;
00241         Gdiplus::SolidBrush* gdipBrush;
00242         while(pos) {
00243                 gdipBrushTable.GetNextAssoc(pos, pt, gdipBrush);
00244                 delete gdipBrush;
00245         }
00246 }
00247 
00248 void CGraphics::CreateFonts(CFont** font, Gdiplus::Font** gdipFont, int boldness)
00249 {
00250         for (int i = 0; i < GME_FONT_KIND_NUM; i++) {
00251                 font[i] = new CFont();
00252                 font[i]->CreateFont(fontSizes[i],0,0,0,boldness,0,0,0,ANSI_CHARSET,
00253                                                         OUT_DEVICE_PRECIS,CLIP_DEFAULT_PRECIS,
00254                                                         PROOF_QUALITY,FF_SWISS,_T("Arial"));
00255 
00256                 CDC dc;
00257                 dc.CreateCompatibleDC(NULL);
00258                 LOGFONT logFont;
00259                 font[i]->GetLogFont(&logFont);
00260                 gdipFont[i] = new Gdiplus::Font( dc.m_hDC, &logFont );
00261         }
00262 }
00263 
00264 Gdiplus::Font* CGraphics::GetGdipFont(GMEFontKind kind)
00265 {
00266         return GetGdipFont(kind, fontBoldness[kind], fontSemiboldness[kind]);
00267 }
00268 
00269 Gdiplus::Font* CGraphics::GetGdipFont(int kindsize, bool bold, bool semibold)
00270 {
00271         return bold ? boldGdipFonts[kindsize] : (semibold ? semiboldGdipFonts[kindsize] : normalGdipFonts[kindsize]);
00272 }
00273 
00274 Gdiplus::Pen* CGraphics::GetGdipPen2(Gdiplus::Graphics* gdip, COLORREF color, GMEConnLineType lineType,
00275                                                                          bool isViewMagnified, int width)
00276 {
00277         // TODO
00278 //      HDC hDC = gdip->GetHDC();
00279 //      bool isPrinting = GetDeviceCaps(hDC, TECHNOLOGY) == DT_RASPRINTER;
00280 //      gdip->ReleaseHDC(hDC);
00281         return GetGdipPen(gdip, color, /*isPrinting*/ false, lineType, isViewMagnified, width);
00282 }
00283 
00284 Gdiplus::Pen* CGraphics::GetGdipPen(Gdiplus::Graphics* gdip, COLORREF color, bool isPrinting, GMEConnLineType lineType,
00285                                                                         bool isViewMagnified, int width)
00286 {
00287         CString chBuffer;
00288         chBuffer.Format(_T("%x-%d-%d-%d-%ld"), color, isPrinting, lineType, isViewMagnified, width);
00289         std::map<CString,Gdiplus::Pen*>::iterator it = m_mapGdipPens.find(chBuffer);
00290         if (it != m_mapGdipPens.end())
00291                 return it->second;
00292 
00293         Gdiplus::Color gdipColor(GetRValue(color), GetGValue(color), GetBValue(color));
00294         float fWidth = static_cast<float> (isPrinting ? 1 : width);
00295         Gdiplus::Pen* pen = new Gdiplus::Pen(gdipColor, fWidth);
00296         if (lineType == GME_LINE_DASH) {
00297                 Gdiplus::REAL dashPatternVals[2] = {
00298                         5.0f,   // dash length 5
00299                         2.0f    // space length 2
00300                 };
00301                 pen->SetDashPattern(dashPatternVals, 2);
00302                 pen->SetDashStyle(Gdiplus::DashStyleCustom);
00303                 pen->SetDashCap(Gdiplus::DashCapRound);
00304         } else if (lineType == GME_LINE_CUSTOMIZED) {
00305                 pen->SetDashStyle(Gdiplus::DashStyleDashDotDot);
00306                 pen->SetDashCap(Gdiplus::DashCapRound);
00307 //      } else {
00308 //              pen->SetDashStyle(Gdiplus::DashStyleSolid);
00309         }
00310 
00311         m_mapGdipPens.insert(std::map<CString,Gdiplus::Pen*>::value_type(chBuffer, pen));
00312         return pen;
00313 }
00314 
00315 Gdiplus::SolidBrush* CGraphics::GetGdipBrush(COLORREF color)
00316 {
00317         Gdiplus::SolidBrush* brush = NULL;
00318         if(!(gdipBrushes.Lookup((void*)color, brush))) {
00319                 brush = new Gdiplus::SolidBrush(Gdiplus::Color(GetRValue(color), GetGValue(color), GetBValue(color)));
00320                 gdipBrushes.SetAt((void*)color, brush);
00321         }
00322         ASSERT(brush);
00323         return brush;
00324 }
00325 
00326 void CGraphics::DrawGrid(Gdiplus::Graphics* gdip, int xSpace, int ySpace, int maxx, int maxy, COLORREF color)
00327 {
00328         Gdiplus::Pen* pen = GetGdipPen2(gdip, color);
00329         for(int x = 0 ; x < maxx; x += xSpace)
00330                 gdip->DrawLine(pen, x, 0, x, maxy);
00331         for(int y = 0; y < maxy; y += ySpace)
00332                 gdip->DrawLine(pen, 0, y, maxx, y);
00333 }
00334 
00335 typedef std::pair<long,long> Long_Pair;
00336 
00337 void CGraphics::DrawConnection(Gdiplus::Graphics* gdip, const CPointList& points, const std::vector<long>& customizedEdgeIndexes,
00338                                                            COLORREF color, GMEConnLineType lineType, int srcEnd, int dstEnd, bool isViewMagnified,
00339                                                            bool drawBullets, int width)
00340 {
00341         if (points.GetCount() == 0)
00342                 return;
00343 
00344         long numEdges = points.GetCount() - 1;
00345         if (numEdges < 1) {
00346                 ASSERT(false);
00347                 return;
00348         }
00349 
00350         // TODO?
00351 //      HDC hDC = gdip->GetHDC();
00352         bool isPrinting = false;        //GetDeviceCaps(hDC, TECHNOLOGY) == DT_RASPRINTER;
00353 //      gdip->ReleaseHDC(hDC);
00354 //      if (isPrinting)
00355 //              color = GME_BLACK_COLOR;
00356 
00357         Gdiplus::Brush* brush = GetGdipBrush(color);
00358         Gdiplus::Brush* bulletBrush = brush;
00359         long bulletOffset = (width + 4) / 2;
00360         long bulletRadius = width + 4;
00361 
00362         if (customizedEdgeIndexes.size() > 0)   {
00363                 std::map<long,long> customizedIndexes; // FIXME if customizedEdgeIndexes is sorted, use binary search to avoid allocations
00364                 // convert array to a map for easier lookup
00365                 std::vector<long>::const_iterator ii = customizedEdgeIndexes.begin();
00366                 while (ii != customizedEdgeIndexes.end())
00367                 {
00368                         customizedIndexes.insert(Long_Pair(*ii, 0));
00369                         ++ii;
00370                 }
00371                 std::map<long,long>::const_iterator indIter;
00372 
00373                 CPoint last;
00374                 POSITION pos = points.GetHeadPosition();
00375                 if (pos) {
00376                         CPoint pt = points.GetNext(pos);
00377                         last = pt;
00378                         long currEdgeIndex = 0;
00379                         while (pos) {
00380                                 pt = points.GetNext(pos);
00381                                 Gdiplus::Pen* pen;
00382                                 indIter = customizedIndexes.find(currEdgeIndex);
00383                                 if (indIter != customizedIndexes.end()) {
00384                                         pen = GetGdipPen(gdip, color, isPrinting, GME_LINE_CUSTOMIZED, isViewMagnified, width);
00385                                 } else {
00386                                         pen = GetGdipPen(gdip, color, isPrinting, lineType, isViewMagnified, width);
00387                                 }
00388                                 gdip->DrawLine(pen, last.x, last.y, pt.x, pt.y);
00389                                 if (drawBullets && currEdgeIndex < numEdges - 1) {
00390                                         gdip->FillEllipse(bulletBrush, pt.x - bulletOffset, pt.y - bulletOffset, bulletRadius, bulletRadius);
00391                                 }
00392                                 last = pt;
00393                                 currEdgeIndex++;
00394                         }
00395                 }
00396         }
00397         else {
00398                 // Same pen for all edges. Use DrawLines.
00399                 using namespace Gdiplus;
00400                 std::vector<Point> gpoints;
00401                 gpoints.reserve(points.GetSize());
00402                 POSITION pos = points.GetHeadPosition();
00403                 while (pos) {
00404                         CPoint pt = points.GetNext(pos);
00405                         gpoints.push_back(Point(pt.x, pt.y));
00406                 }
00407                 Pen* pen = GetGdipPen(gdip, color, isPrinting, lineType, isViewMagnified, width);
00408                 gdip->DrawLines(pen, &gpoints[0], gpoints.size()); // n.b. this is different than a sequence of DrawLine()s (GME-419)
00409         }
00410 
00411         Gdiplus::Pen* headpen = GetGdipPen(gdip, color, isPrinting);
00412 
00413         {
00414         POSITION pos2 = points.GetHeadPosition();
00415         CPoint first = points.GetNext(pos2);
00416         CPoint second = points.GetNext(pos2);
00417 
00418         Gdiplus::Brush* headBrush = NULL;
00419         headBrush = GetGdipBrush((srcEnd == GME_EMPTYDIAMOND_END ||
00420                                                           srcEnd == GME_EMPTYAPEX_END ||
00421                                                           srcEnd == GME_EMPTYBULLET_END) ? GME_WHITE_COLOR : color);
00422 
00423         DrawArrow(gdip, headpen, headBrush, second, first, srcEnd, width > 2);
00424         }
00425 
00426         {
00427         POSITION pos = points.GetTailPosition();
00428         CPoint last = points.GetPrev(pos);
00429         CPoint beforeLast = points.GetPrev(pos);
00430 
00431         Gdiplus::Brush* headBrush = NULL;
00432         headBrush = GetGdipBrush((dstEnd == GME_EMPTYDIAMOND_END ||
00433                                                           dstEnd == GME_EMPTYAPEX_END ||
00434                                                           dstEnd == GME_EMPTYBULLET_END) ? GME_WHITE_COLOR : color);
00435 
00436         DrawArrow(gdip, headpen, headBrush, beforeLast, last, dstEnd, width > 2);
00437         }
00438 }
00439 
00440 void CGraphics::DrawArrow(Gdiplus::Graphics* gdip, Gdiplus::Pen* pen, Gdiplus::Brush* brush,
00441                                                   const CPoint& beforeLast, const CPoint& last, int iEnd, bool bold)
00442 {
00443         if (iEnd == GME_BUTT_END) {
00444                 return;
00445         }
00446         int dir = 0;
00447         double alpha = 0.0;
00448         bool skew = false;
00449         if (beforeLast.x == last.x)
00450         {
00451                 if (beforeLast.y > last.y)
00452                 {
00453                         dir = GME_UP_DIRECTION;
00454                 }
00455                 else
00456                 {
00457                         dir = GME_DOWN_DIRECTION;
00458                 }
00459         }
00460         else if (beforeLast.y == last.y)
00461         {
00462                 if (beforeLast.x > last.x)
00463                 {
00464                         dir = GME_LEFT_DIRECTION;
00465                 }
00466                 else
00467                 {
00468                         dir = GME_RIGHT_DIRECTION;
00469                 }
00470         }
00471         else    // skew
00472         {
00473                 skew = true;
00474                 dir = GME_RIGHT_DIRECTION;
00475                 alpha = atan2((double)last.y - beforeLast.y, (double)last.x - beforeLast.x);
00476         }
00477 
00478         switch (iEnd) {
00479                 case GME_ARROW_END :
00480                         arrows[dir]->Draw(gdip, pen, brush, last, false, alpha, bold);
00481                         break;
00482                 case GME_DIAMOND_END :
00483                 case GME_EMPTYDIAMOND_END :
00484                         diamonds[dir]->Draw(gdip, pen, brush, last, iEnd == GME_EMPTYDIAMOND_END, alpha, bold);
00485                         break;
00486                 case GME_APEX_END :
00487                 case GME_EMPTYAPEX_END :
00488                         apexes[dir]->Draw(gdip, pen, brush, last, iEnd == GME_EMPTYAPEX_END, alpha, bold);
00489                         break;
00490                 case GME_BULLET_END :
00491                 case GME_EMPTYBULLET_END :
00492                         bullets[dir]->Draw(gdip, pen, brush, last, iEnd == GME_EMPTYBULLET_END, alpha, bold);
00493                         break;
00494                 case GME_HALFARROWLEFT_END :
00495                         leftHalfArrows[dir]->Draw(gdip, pen, brush, last, true, alpha, bold);
00496                         break;
00497                 case GME_HALFARROWRIGHT_END :
00498                         rightHalfArrows[dir]->Draw(gdip, pen, brush, last, true, alpha, bold);
00499                         break;
00500         }
00501 }
00502 
00503 void CGraphics::DrawGdipText(Gdiplus::Graphics* gdip, const CString& txt, const CPoint& pt, Gdiplus::Font* font, COLORREF color, int align)
00504 {
00505         if (font == NULL)
00506                 return;
00507 
00508         Gdiplus::StringFormat format;
00509         Gdiplus::StringAlignment horizontalAlignment;
00510         if ((align & TA_CENTER) == TA_CENTER) {
00511                 horizontalAlignment = Gdiplus::StringAlignmentCenter;
00512         } else if ((align & TA_RIGHT) == TA_RIGHT) {
00513                 horizontalAlignment = Gdiplus::StringAlignmentFar;
00514         } else {        // TA_LEFT
00515                 horizontalAlignment = Gdiplus::StringAlignmentNear;
00516         }
00517         format.SetAlignment(horizontalAlignment);
00518         Gdiplus::StringAlignment verticalAlignment;
00519         if ((align & TA_BASELINE) == TA_BASELINE) {
00520                 verticalAlignment = Gdiplus::StringAlignmentCenter;
00521         } else if ((align & TA_BOTTOM) == TA_BOTTOM) {
00522                 verticalAlignment = Gdiplus::StringAlignmentFar;
00523         } else {        // TA_TOP
00524                 verticalAlignment = Gdiplus::StringAlignmentNear;
00525         }
00526         format.SetLineAlignment(verticalAlignment);
00527         format.SetFormatFlags(format.GetFormatFlags() | Gdiplus::StringFormatFlagsNoWrap);
00528         format.SetTrimming(Gdiplus::StringTrimmingEllipsisPath);
00529 
00530         // TODO
00531 //      HDC hDC = gdip->GetHDC();
00532 //      COLORREF textColor = GetDeviceCaps(hDC, TECHNOLOGY) == DT_RASPRINTER ? GME_BLACK_COLOR : color;
00533 //      gdip->ReleaseHDC(hDC);
00534         COLORREF textColor = color;
00535 
00536         Gdiplus::SolidBrush textBrush(Gdiplus::Color(GetRValue(textColor),
00537                                                                                                  GetGValue(textColor),
00538                                                                                                  GetBValue(textColor)));
00539 
00540         Gdiplus::PointF pointF(static_cast<float> (pt.x),
00541                                                    static_cast<float> (pt.y));
00542 
00543         gdip->DrawString(txt, txt.GetLength(), font, pointF, &format, &textBrush);
00544 }
00545 
00546 Gdiplus::RectF CGraphics::MeasureText2(Gdiplus::Graphics* gdip, const CString& txt, const CPoint& pt, Gdiplus::Font* font)
00547 {
00548         Gdiplus::PointF pointF(static_cast<float> (pt.x),
00549                                                    static_cast<float> (pt.y));
00550 
00551         Gdiplus::RectF rectF;
00552         gdip->MeasureString(txt, txt.GetLength(), font, pointF, &rectF);
00553         return rectF;
00554 }
00555 
00556 CSize CGraphics::MeasureText(Gdiplus::Graphics* gdip, const CString& txt, const CPoint& pt, Gdiplus::Font* font)
00557 {
00558         Gdiplus::RectF rectF = MeasureText2(gdip, txt, pt, font);
00559         Gdiplus::SizeF sizeF;
00560         rectF.GetSize(&sizeF);
00561         CSize size(static_cast<long> (sizeF.Width), static_cast<long> (sizeF.Height));
00562         return size;
00563 }