2017-07-12 139 views
1

我正在尋找一種解決方案,以便如何從設備句柄(HDC)中提取當前剪切路徑作爲一組點(移動到,行到貝塞爾曲線)使用WinAPI調用。例如,WinAPI允許使用AND,OR,XOR和DIFF邏輯運算符創建複雜的剪切路徑,並且可以以不同的方式使用它。例如,下面的代碼將創建三個圈,並與一些邏輯(模式1和模式2)進行合併:從設備句柄(WinAPI)獲取當前剪切路徑

void clippingTest(HDC dc, int x, int y, std::wstring const &text, int mode1, int mode2){ 
    SaveDC(dc); 

    HBRUSH redBrush = CreateSolidBrush(RGB(255, 0, 0)); 
    HBRUSH greenBrush = CreateSolidBrush(RGB(0, 255, 0)); 
    HBRUSH blueBrush = CreateSolidBrush(RGB(0, 0, 255)); 

    LOGFONT lf = {0}; 
    lf.lfHeight = -MulDiv(12, GetDeviceCaps(dc, LOGPIXELSY), 72); 
    std::wstring const faceName = L"Arial"; 
    wcscpy_s(lf.lfFaceName, LF_FACESIZE, faceName.c_str()); 
    HFONT font = CreateFontIndirect(&lf); 

    RECT rect = {x, y, x + 700, y + 650}; 
    FillRect(dc, &rect, greenBrush); 

    BeginPath(dc); 
    Ellipse(dc, x, y, x + 400, y + 400); 
    //drawStar(dc, x, y); 
    EndPath(dc); 
    SelectClipPath(dc, RGN_COPY); 

    BeginPath(dc); 
    Ellipse(dc, x + 300, y, x + 700, y + 400); 
    //drawStar(dc, x, y); 
    EndPath(dc); 
    SelectClipPath(dc, mode1); 

    BeginPath(dc); 
    Ellipse(dc, x + 150, y + 250, x + 550, y + 650); 
    //drawStar(dc, x + 300, y); 
    EndPath(dc); 
    SelectClipPath(dc, mode2); 

    SetPolyFillMode(dc, ALTERNATE); 
    FillRect(dc, &rect, blueBrush); 

    BeginPath(dc); 
    Rectangle(dc, rect.left, rect.top, rect.right, rect.bottom); 
    EndPath(dc); 
    SelectClipPath(dc, RGN_COPY); 

    SelectObject(dc, font); 
    DrawText(dc, text.c_str(), text.length(), &rect, DT_CENTER | DT_TOP); 

    RestoreDC(dc, -1); 
} 

The result of clipping here

而我感興趣的是如何以獲得進一步的處理結果路徑。

解決方案之一可以在其他HDC上繪製剪切路徑,創建透明圖像並將其用於下一個繪圖。但是這種方法會增加結果文件(例如PDF)。

回答

0

找到了一個解決方案,它允許用矩形近似結果區域。

void Emf2PdfEngine::selectClippingPath(void){ 
    Rgn rgn(CreateRectRgn(0, 0, 1, 1)); // RAII for HRGN object 
    if (!GetClipRgn(mHdc, rgn)) 
     return; 

    DWORD const rgnSize = GetRegionData(rgn, 0, nullptr); 
    std::vector<uint8_t> rgnData(rgnSize); 
    GetRegionData(rgn, rgnSize, (RGNDATA *) rgnData.data()); 
    RGNDATA *rawData = (RGNDATA *) rgnData.data(); 

    uint32_t const count = rawData->rdh.nCount; // count of RECT objects 
    if (!count) 
     return; 

    mCurrentDeviceState->mIsClipped = true; 
    mCurrentDeviceState->mClippingPathPoints.resize(count * 2); 
    mCurrentDeviceState->mClippingPathTypes.resize(count * 2); 

    RECT *rect = (RECT *) rawData->Buffer; 
    for (std::size_t i = 0; i < count; ++i){ 
     mCurrentDeviceState->mClippingPathPoints[i * 2] = {rect[i].left, rect[i].top}; 
     mCurrentDeviceState->mClippingPathPoints[i * 2 + 1] = {rect[i].right - rect[i].left, rect[i].bottom - rect[i].top}; 
     mCurrentDeviceState->mClippingPathTypes[i * 2] = PT_RECT; 
     mCurrentDeviceState->mClippingPathTypes[i * 2 + 1] = PT_RECT;// | PT_CLOSEFIGURE; 
    } 
    }