2017-07-12 141 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; 
    } 
    }