2017-07-12 17 views
1

Je cherche une solution pour extraire un chemin de détourage courant d'un handle de périphérique (HDC) en un ensemble de points (déplacement vers, line to, courbes de Bézier) avec en utilisant des appels WinAPI. Par exemple, WinAPI permet de créer un tracé de détourage complexe en utilisant les opérateurs logiques AND, OR, XOR et DIFF et il peut être utilisé de différentes manières. Par exemple, le code ci-dessous crée trois cercles et fusionner avec une certaine logique (mode1 et mode2):Récupère le chemin de détourage courant depuis le handle de périphérique (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

Je suis intéressé par la façon d'obtenir le chemin de résultat pour un traitement ultérieur. L'une des solutions consiste à dessiner un tracé de détourage sur d'autres HDC, à créer une image transparente et à l'utiliser pour le dessin suivant. Mais cette approche va augmenter le fichier résultat (PDF, par exemple).

Répondre

0

Ont trouvé une solution qui permet d'approximer la zone de résultat avec des rectangles.

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; 
    } 
    }