#include #include #include #include #include #include #include using namespace Gdiplus; #include "wndstuff.h" GraphicsPath gppath; GraphicsPath widepath; GraphicsPath clippath; TextureBrush *texturebrush = NULL; PointF lastpoint(-1,-1); Bitmap *offscreenbitmap = NULL; int subpathlength = 0; int ScaleColorMode = 0; WCHAR savedFilename[255]; void RemakePath(GraphicsPath *linepath, GraphicsPath *bezpath, BOOL bezmode) { GraphicsPath *temppath = linepath->Clone(); temppath->CloseFigure(); bezpath->Reset(); PointF *points = new PointF[temppath->GetPointCount()]; BYTE *types = new BYTE[temppath->GetPointCount()]; temppath->GetPathPoints(points, temppath->GetPointCount()); temppath->GetPathTypes(types, temppath->GetPointCount()); int last = 0; for (int i=0; iGetPointCount(); i++) { if (types[i] & PathPointTypeCloseSubpath) { if (i-last+1 > 2) { if (!bezmode) { bezpath->AddPolygon(points+last, i-last+1); } else { bezpath->AddClosedCurve(points+last, i-last+1); } last = i+1; } } } delete points; delete types; delete temppath; } void SplitPath(BOOL bezmode, BOOL before, BOOL after, float flatness) { if (gppath.GetPointCount() < 3) return; RemakePath(&gppath, &widepath, bezmode); if (widepath.GetPointCount() > 2) { Pen pen(Color(0xff000000), 20); pen.SetLineJoin(LineJoinMiter); pen.SetMiterLimit(5); Matrix matrix; if (before) widepath.Outline(NULL, flatness); widepath.Widen(&pen, NULL, flatness); if (after) widepath.Outline(NULL, flatness); } } void ClosePath() { if (gppath.GetPointCount() < 1) return; gppath.CloseFigure(); lastpoint = PointF(-1,-1); } void ClearPath() { lastpoint = PointF(-1,-1); gppath.Reset(); widepath.Reset(); } void ClipPath(BOOL bezmode) { clippath.Reset(); GraphicsPath remadepath; RemakePath(&gppath, &remadepath, bezmode); clippath.AddPath(&remadepath, FALSE); ClearPath(); } void ClearClipPath() { clippath.Reset(); } void AddPoint(INT x, INT y) { if (!(lastpoint.X == -1 && lastpoint.Y == -1)) { gppath.AddLine(lastpoint, PointF((float)x, (float)y)); } lastpoint = PointF((float)x, (float)y); } void OpenPath(char *filename) { FILE *f = fopen(filename, "rt"); INT count; fscanf(f, "%i", &count); for (INT i=0; iGetWidth(), bitmap->GetHeight()); if (bitmap->LockBits(&rect, ImageLockModeRead, PixelFormat32bppARGB, &bmpData) == Ok) { ARGB *data; for (UINT y=0; yGetHeight(); y++) { data = (ARGB*)((BYTE*)bmpData.Scan0+(y*bmpData.Stride)); for (UINT x=0; xGetWidth(); x++) { *data = ScaleColor(Color(*data), x, bitmap->GetWidth()).GetValue(); data++; } } BitmapData bmpDataDest; if (destBitmap->LockBits(&rect, ImageLockModeWrite, PixelFormat32bppARGB, &bmpDataDest) == Ok) { memcpy(bmpDataDest.Scan0, bmpData.Scan0, bitmap->GetWidth() * bitmap->GetHeight() * sizeof(ARGB)); destBitmap->UnlockBits(&bmpDataDest); } bitmap->UnlockBits(&bmpData); } } void ChangeTexture(const WCHAR *filename) { wcsncpy(savedFilename, filename, 255); delete texturebrush; Bitmap image(filename); Bitmap image2(image.GetWidth(), image.GetHeight(), PixelFormat32bppARGB); ScaleColors(&image2, &image); texturebrush = new TextureBrush(&image2); } void Resize(INT x, INT y) { delete offscreenbitmap; offscreenbitmap = new Bitmap(x, y, PixelFormat32bppPARGB); } void CleanUp() { delete offscreenbitmap; delete texturebrush; } VOID Print(HWND hwnd, float flatness, PtFlag flags) { PRINTDLG printdlg; memset(&printdlg, 0, sizeof(PRINTDLG)); printdlg.lStructSize = sizeof(PRINTDLG); printdlg.hwndOwner = hwnd; printdlg.hDevMode = NULL; printdlg.hDevNames = NULL; printdlg.hDC = NULL; printdlg.Flags = PD_RETURNDC; if (PrintDlg(&printdlg)) { DOCINFO di; memset(&di, 0, sizeof(DOCINFO)); di.cbSize = sizeof(DOCINFO); di.lpszDocName = "Path Printing Test"; di.lpszOutput = (LPTSTR)NULL; di.lpszDatatype = (LPTSTR)NULL; di.fwType = 0; DEVMODE *devmode = (DEVMODE*)GlobalLock(printdlg.hDevMode); if (devmode == NULL) return; HANDLE hprinter; OpenPrinter((LPSTR)devmode->dmDeviceName, &hprinter, NULL); GlobalUnlock(printdlg.hDevMode); StartDoc(printdlg.hDC, &di); StartPage(printdlg.hDC); DrawPath(hwnd, &printdlg.hDC, &hprinter, flatness, flags); EndPage(printdlg.hDC); EndDoc(printdlg.hDC); } else { DWORD error = CommDlgExtendedError(); if (error) { char errormessage[100]; sprintf(errormessage, "PrintDlg error: %d", error); MessageBox(hwnd, errormessage, "PrintDlg error", MB_OK); } } } void DrawPath(HWND hwnd, HDC *phdc, HANDLE *hprinter, float flatness, PtFlag flags) { if (!offscreenbitmap) return; Graphics *renderinggraphics; if (phdc) { renderinggraphics = new Graphics(*phdc, *hprinter); } else { renderinggraphics = new Graphics(offscreenbitmap); } RECT rect; GetClientRect(hwnd, &rect); Brush *background; if (flags & PTBackgroundGradFillFlag) { background = new LinearGradientBrush(Point(0, 0), Point((rect.right-rect.left)/4, 0), Color(0xffffffff), Color(0xff0000ff)); ((LinearGradientBrush*)background)->SetWrapMode(WrapModeTileFlipX); } else { background = new SolidBrush(Color(0xffffffff)); } renderinggraphics->FillRectangle(background, Rect(rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top)); delete background; renderinggraphics->SetSmoothingMode(SmoothingModeAntiAlias); if (gppath.GetPointCount() > 0) { SplitPath(flags & PtBezierFlag, flags & PtOutlineBeforeFlag, flags & PtOutlineAfterFlag, flatness); if (clippath.GetPointCount() > 2) { renderinggraphics->SetClip(&clippath); } if (flags & PtTextureFillFlag) { if (!texturebrush) ChangeTexture(L"mycomputer.jpg"); GraphicsPath bezpath; RemakePath(&gppath, &bezpath, flags & PtBezierFlag); if (flags & PtOutlineBeforeFlag) bezpath.Outline(); bezpath.SetFillMode(FillModeWinding); renderinggraphics->FillPath(texturebrush, &bezpath); } if (flags & PtTransSolidFillFlag) { SolidBrush transsolidbrush(Color(0x80ffff00)); GraphicsPath bezpath; RemakePath(&gppath, &bezpath, flags & PtBezierFlag); if (flags & PtOutlineBeforeFlag) bezpath.Outline(); bezpath.SetFillMode(FillModeAlternate); renderinggraphics->FillPath(&transsolidbrush, &bezpath); } if (flags & PtTransGradFillFlag) { GraphicsPath bezpath; RemakePath(&gppath, &bezpath, flags & PtBezierFlag); Matrix m; bezpath.Flatten(&m, flatness); INT count = bezpath.GetPointCount(); if (flags & PtOutlineBeforeFlag) bezpath.Outline(); bezpath.SetFillMode(FillModeAlternate); PathGradientBrush pathgradientbrush(&bezpath); Color *colors = new Color[count]; for (int i=0; iFillPath(&pathgradientbrush, &bezpath); delete colors; } if (!(flags & PtHatchBrushFlag)) { SolidBrush pathbrush(Color(0xffc0c0ff)); renderinggraphics->FillPath(&pathbrush, &widepath); } else { HatchBrush pathbrush(HatchStyleDiagonalBrick, Color(0xff000000), Color(0xffc0c0ff)); renderinggraphics->FillPath(&pathbrush, &widepath); } Pen blackpen(Color(0xff000000), 2); blackpen.SetLineJoin(LineJoinMiter); renderinggraphics->DrawPath(&blackpen, &widepath); renderinggraphics->ResetClip(); SolidBrush solidbrush(0xff0000ff); Pen pathpen(&solidbrush); pathpen.SetLineJoin(LineJoinRound); if (!(flags & PtDashPatternFlag)) { pathpen.SetWidth(6); } else { pathpen.SetWidth(8); pathpen.SetDashStyle(DashStyleDot); pathpen.SetDashCap(DashCapRound); REAL distances[6] = {1.0f, 1.0f, 3.0f, 3.5f, 7.0f, 9.0f}; pathpen.SetDashPattern(distances,6); } renderinggraphics->DrawPath(&pathpen, &gppath); PointF *points = new PointF[gppath.GetPointCount()]; gppath.GetPathPoints(points, gppath.GetPointCount()); for (INT i=0; iFillEllipse(&bluebrush, rect); } delete points; } if (clippath.GetPointCount() > 2) { Pen clippen(Color(0xffff0000), 4); clippen.SetDashStyle(DashStyleDot); clippen.SetLineJoin(LineJoinRound); renderinggraphics->DrawPath(&clippen, &clippath); } SolidBrush darkbluebrush(Color(0xff0000c0)); if (lastpoint.X != -1 && lastpoint.Y != -1) { RectF rect(lastpoint.X-6, lastpoint.Y-6, 12, 12); renderinggraphics->FillEllipse(&darkbluebrush, rect); } delete renderinggraphics; if (phdc == NULL) { HDC hdc = GetDC(hwnd); Graphics *g = new Graphics(hdc); PAINTSTRUCT paintstruct; BeginPaint(hwnd, &paintstruct); g->DrawImage(offscreenbitmap, 0, 0); EndPaint(hwnd, &paintstruct); ReleaseDC(hwnd, hdc); delete g; } }