/** get the complex path made from the internal complex region @remarks only for D2D impl because we can only clip with geometry paths & not directly with GDI region return NULL if region is a simple region (ie equal to region bounds) */ VGraphicPath *VRegion::GetComplexPath() const { HRGN hrgn = (RgnRef)(*this); Gdiplus::Region region( hrgn); Gdiplus::Matrix matIdentity; UINT numRect = region.GetRegionScansCount(&matIdentity); if (numRect > 1) { VGraphicPath *path = new VGraphicPath(); if (!path) return NULL; Gdiplus::Rect rects[8]; Gdiplus::Rect *pRect = rects; if (numRect > 8) pRect = new Gdiplus::Rect[numRect]; Gdiplus::Status status = region.GetRegionScans(&matIdentity, pRect, (INT *)&numRect); if (status == Gdiplus::Ok) { path->Begin(); Gdiplus::Rect *curRect = pRect; for (int i = 0; i < numRect; i++, curRect++) { if (i == 0) path->AddRect( VRect( curRect->GetLeft(), curRect->GetTop(), curRect->GetRight()-curRect->GetLeft(), curRect->GetBottom()-curRect->GetTop())); else { VGraphicPath pathRect; pathRect.Begin(); pathRect.AddRect( VRect( curRect->GetLeft(), curRect->GetTop(), curRect->GetRight()-curRect->GetLeft(), curRect->GetBottom()-curRect->GetTop())); pathRect.End(); path->Union( pathRect); } } path->End(); } else { delete path; path = NULL; } if (numRect > 8) delete [] pRect; return path; } else return NULL; }
bool TextOutlineStrategy::MeasureString( Gdiplus::Graphics* pGraphics, Gdiplus::FontFamily* pFontFamily, Gdiplus::FontStyle fontStyle, int nfontSize, const wchar_t*pszText, Gdiplus::Rect rtDraw, Gdiplus::StringFormat* pStrFormat, float* pfDestWidth, float* pfDestHeight ) { using namespace Gdiplus; GraphicsPath path; Status status = path.AddString(pszText,wcslen(pszText),pFontFamily,fontStyle,nfontSize,rtDraw,pStrFormat); if(status!=Ok) return false; *pfDestWidth= rtDraw.GetLeft(); *pfDestHeight= rtDraw.GetTop(); bool b = GDIPath::MeasureGraphicsPath(pGraphics, &path, pfDestWidth, pfDestHeight); if(false==b) return false; float pixelThick = 0.0f; b = GDIPath::ConvertToPixels(pGraphics,m_nThickness,0.0f,&pixelThick,NULL); if(false==b) return false; *pfDestWidth += pixelThick; *pfDestHeight += pixelThick; return true; }
bool TextNoOutlineStrategy::MeasureString( Gdiplus::Graphics* pGraphics, Gdiplus::FontFamily* pFontFamily, Gdiplus::FontStyle fontStyle, int nfontSize, const wchar_t*pszText, Gdiplus::Rect rtDraw, Gdiplus::StringFormat* pStrFormat, float* pfPixelsStartX, float* pfPixelsStartY, float* pfDestWidth, float* pfDestHeight ) { using namespace Gdiplus; GraphicsPath path; Status status = path.AddString(pszText,wcslen(pszText),pFontFamily,fontStyle,nfontSize,rtDraw,pStrFormat); if(status!=Ok) return false; *pfDestWidth= rtDraw.GetLeft(); *pfDestHeight= rtDraw.GetTop(); bool b = GDIPath::MeasureGraphicsPath(pGraphics, &path, pfPixelsStartX, pfPixelsStartY, pfDestWidth, pfDestHeight); return b; }
void VPictureData_GDIPlus_Vector::_InitSize()const { if(fMetafile) { Gdiplus::Rect rect; Gdiplus::MetafileHeader gh; fMetafile->GetMetafileHeader(&gh); //sLONG width = (short) ( ( (long) gh.EmfHeader.rclFrame.right * 96L ) / 2540L ); //sLONG height = (short) ( ( (long) gh.EmfHeader.rclFrame.bottom * 96L ) / 2540L ); /*re1.Width= gh.EmfHeader.rclFrame.right * gh.EmfHeader.szlDevice.cx / (gh.EmfHeader.szlMillimeters.cx*100); re1.Height= gh.EmfHeader.rclFrame.bottom * gh.EmfHeader.szlDevice.cy / (gh.EmfHeader.szlMillimeters.cy*100); re1.Width=re1.Width * (96.0/gh.GetDpiX()); re1.Height=re1.Height * (96.0/gh.GetDpiY());*/ gh.GetBounds(&rect); fBounds.SetCoords(rect.GetLeft(),rect.GetTop(),rect.GetRight()-rect.GetLeft(),rect.GetBottom()-rect.GetTop()); } }
void PrintRichEdit(HWND hwnd, Gdiplus::Graphics* graphics, Gdiplus::Bitmap* background, Gdiplus::Rect layoutArea) { using namespace Gdiplus; //Calculate the area to render. HDC hdc1 = ::GetDC(hwnd); double anInchX = 1440 / GetDeviceCaps(hdc1, LOGPIXELSX); double anInchY = 1440 / GetDeviceCaps(hdc1, LOGPIXELSY); ReleaseDC(hwnd,hdc1); //double anInch = 1440.0 / GetDeviceCaps(hdc1, LOGPIXELSX); RECT rectLayoutArea; rectLayoutArea.top = (int)(layoutArea.GetTop() * anInchY); rectLayoutArea.bottom = (int)(layoutArea.GetBottom() * anInchY); rectLayoutArea.left = (int)(layoutArea.GetLeft() *anInchX ); rectLayoutArea.right = (int)(layoutArea.GetRight() * anInchX); HDC hdc = graphics->GetHDC(); Gdiplus::Graphics gr2(hdc); SolidBrush br(Color(255,255,255)); // We need to draw background on new HDC, otherwise the text will look ugly Status st = gr2.DrawImage(background,layoutArea.GetLeft(),layoutArea.GetTop(),layoutArea.GetLeft(), layoutArea.GetTop(), layoutArea.Width, layoutArea.Height,Gdiplus::UnitPixel/*gr2.GetPageUnit()*/); FORMATRANGE fmtRange; fmtRange.chrg.cpMax = -1; //Indicate character from to character to fmtRange.chrg.cpMin = 0; fmtRange.hdc = hdc; //Use the same DC for measuring and rendering fmtRange.hdcTarget = hdc; //Point at printer hDC fmtRange.rc = rectLayoutArea; //Indicate the area on page to print fmtRange.rcPage = rectLayoutArea; //Indicate size of page int characterCount = ::SendMessage(hwnd, EM_FORMATRANGE, 1, (LPARAM)&fmtRange); //Release the device context handle obtained by a previous call graphics->ReleaseHDC(hdc); }
bool TextNoOutlineStrategy::GdiMeasureStringRealHeight( Gdiplus::Graphics* pGraphics, LOGFONTW* pLogFont, const wchar_t*pszText, Gdiplus::Rect rtDraw, float* pfPixelsStartX, float* pfPixelsStartY, float* pfDestWidth, float* pfDestHeight ) { using namespace Gdiplus; Gdiplus::GraphicsPath* pPath=NULL; bool b = GDIPath::GetStringPath( pGraphics, &pPath, pszText, pLogFont, rtDraw); if(false==b) { if(pPath) { delete pPath; pPath = NULL; } return false; } *pfDestWidth= rtDraw.GetLeft(); *pfDestHeight= rtDraw.GetTop(); b = GDIPath::MeasureGraphicsPathRealHeight(pGraphics, pPath, pfPixelsStartX, pfPixelsStartY, pfDestWidth, pfDestHeight); if(pPath) { delete pPath; pPath = NULL; } return b; }
HRESULT Action( const P* pts, size_t count, const Gdiplus::Rect& clip, ScanConvertCallback callback, INT_PTR hint) { if(count <= 0) return E_INVALIDARG; if(pts == NULL) return E_INVALIDARG; if(callback == NULL) return E_INVALIDARG; n = (INT) count; pt = pts; /// initialize index array as natrual order std::vector<INT> idx(n); active.resize(n); for(INT i = 0; i < n; i ++) { idx[i] = i; } /// Sort idx by the order of pt[idx[k]].Y std::sort(&idx[0], &idx[0] + n, CompareIndex(pt)); nact = 0; /// number of active edges, init as empty INT k = 0; /// idx[k] is the next vertex to precess INT y0 = max(clip.GetTop(), xtl::FloorCast<INT>(pt[idx[0]].Y)); /// the topmost scanline INT y1 = min(clip.GetBottom(), xtl::CeilCast<INT>(pt[idx[n-1]].Y)); /// the bottom scanline /// step through scanlines /// scanline y is at y+.5 in continuous coordinates for(INT y = y0; y < y1; y ++) { /// check vertices between previous scanline and current one, if any for (; (k < n) && (pt[idx[k]].Y <= y); k++) { /// to simplify, if pt.y = y+.5, pretend it's above /// invariant: y-.5 < pt[i].y <= y+.5 INT i = idx[k]; /// insert or delete edges before and after vertex i /// (i-1 to i, and i to i+1) from active list if they cross scanline y INT j = i > 0 ? i-1 : n-1; /// vertex previous to i if (pt[j].Y <= y) /// old edge, remove from active list { DeleteActiveEdge(j); } else if (pt[j].Y > y) /// new edge, add to active list { InsertActiveEdge(j, y); } j = i < (n - 1) ? i+1 : 0; /// vertex next after i if (pt[j].Y <= y) /// old edge, remove from active list { DeleteActiveEdge(i); } else if (pt[j].Y > y) /// new edge, add to active list { InsertActiveEdge(i, y); } } /// sort active edge list by active[j].x std::sort(&active[0], &active[0] + nact, CompareEdge()); /// draw horizontal segments for scanline y for (INT j=0; j < nact; j += 2) /// draw horizontal segments { /// span 'tween j & j+1 is inside, span tween j+1 & j+2 is outside INT xl = xtl::CeilCast<INT>(active[j].x); /// left end of span if (xl < clip.GetLeft()) xl = clip.GetLeft(); if (xl > clip.GetRight()) xl = clip.GetRight(); INT xr = xtl::CeilCast<INT>(active[j+1].x); /// right end of span if (xr < clip.GetLeft()) xr = clip.GetLeft(); if (xr > clip.GetRight()) xr = clip.GetRight(); if (xl < xr) { /// Invoke call back in span if(!callback(y, xl, xr, hint)) { /// if call back returns false /// return prematurely return S_OK; } } active[j].x += active[j].dx; /// increment edge coords active[j+1].x += active[j+1].dx; } } return S_OK; }
bool TextOutlineStrategy::GdiMeasureStringRealHeight( Gdiplus::Graphics* pGraphics, LOGFONTW* pLogFont, const wchar_t*pszText, Gdiplus::Rect rtDraw, float* pfDestWidth, float* pfDestHeight ) { using namespace Gdiplus; Gdiplus::GraphicsPath* pPath=NULL; bool b = GDIPath::GetStringPath( pGraphics, &pPath, pszText, pLogFont, rtDraw); if(false==b) { if(pPath) { delete pPath; pPath = NULL; } return false; } *pfDestWidth= rtDraw.GetLeft(); *pfDestHeight= rtDraw.GetTop(); b = GDIPath::MeasureGraphicsPathRealHeight(pGraphics, pPath, pfDestWidth, pfDestHeight); if(false==b) { if(pPath) { delete pPath; pPath = NULL; } return false; } float pixelThick = 0.0f; b = GDIPath::ConvertToPixels(pGraphics,m_nThickness,0.0f,&pixelThick,NULL); if(false==b) { if(pPath) { delete pPath; pPath = NULL; } return false; } *pfDestWidth += pixelThick; *pfDestHeight += pixelThick; if(pPath) { delete pPath; pPath = NULL; } return true; }