RRect RLineCache::flush(class IRichCompositor* compositor) { RRect line_rect; // no element yet, need not flush! element_list_t* line = getCachedElements(); if ( line->size() == 0 ) return line_rect; // line mark std::vector<element_list_t::iterator> line_marks; std::vector<short> line_widths; RRect zone = compositor->getMetricsState()->zone; bool wrapline = m_rWrapLine; // line width auto growth if ( zone.size.w == 0 ) wrapline = false; RMetricsState* mstate = compositor->getMetricsState(); RPos pen; RRect temp_linerect; short base_line_pos_y = 0; element_list_t::iterator inner_start_it = line->begin(); line_marks.push_back(line->begin()); // push first line start for ( element_list_t::iterator it = line->begin(); it != line->end(); it++ ) { RMetrics* metrics = (*it)->getMetrics(); // prev composit event (*it)->onCachedCompositBegin(this, pen); // calculate baseline offset short baseline_correct = 0; if ( (*it)->needBaselineCorrect() ) { baseline_correct = m_rBaselinePos; } // first element if ( pen.x == 0 ) { pen.x -= metrics->rect.min_x(); } // set position (*it)->setLocalPositionX(pen.x); (*it)->setLocalPositionY(pen.y + baseline_correct); RRect rect = metrics->rect; rect.pos.x += pen.x; rect.pos.y += baseline_correct; temp_linerect.extend(rect); // process wrapline element_list_t::iterator next_it = it + 1; if ( next_it == line->end() || // last element (*next_it)->isNewlineBefore() || // line-break before next element (*it)->isNewlineFollow() || // line-break after this element ( wrapline && pen.x != 0 // wrap line && pen.x + metrics->advance.x + (*next_it)->getMetrics()->rect.pos.x + (*next_it)->getMetrics()->rect.size.w + getPadding()*2 > zone.size.w && (*next_it)->canLinewrap() ) ) { // correct out of bound correct short y2correct = -temp_linerect.max_y(); for ( element_list_t::iterator inner_it = inner_start_it; inner_it != next_it; inner_it++ ) { RPos pos = (*inner_it)->getLocalPosition(); (*inner_it)->setLocalPositionY(pos.y + y2correct); (*inner_it)->setLocalPositionX(pos.x /*+ x2correct*/); } temp_linerect.pos.y = pen.y; line_rect.extend(temp_linerect); pen.y -= (temp_linerect.size.h + getSpacing()); pen.x = 0; // push next line start line_marks.push_back(next_it); line_widths.push_back(temp_linerect.size.w); inner_start_it = next_it; temp_linerect = RRect(); } else { pen.x += metrics->advance.x; } // post composit event (*it)->onCachedCompositEnd(this, pen); } short align_correct_x = 0; size_t line_mark_idx = 0; if ( getHAlign() == e_align_left ) line_rect.size.w += getPadding() * 2; else line_rect.size.w = RMAX(zone.size.w, line_rect.size.w + getPadding() * 2); // auto rect for ( element_list_t::iterator it = line->begin(); it != line->end(); it++ ) { // prev composit event (*it)->onCachedCompositBegin(this, pen); if ( it == line_marks[line_mark_idx] ) { short lwidth = line_widths[line_mark_idx]; // x correct switch ( getHAlign() ) { case e_align_left: align_correct_x = getPadding(); break; case e_align_center: align_correct_x = ( line_rect.size.w - lwidth ) / 2; break; case e_align_right: align_correct_x = line_rect.size.w - lwidth - getPadding(); break; } line_mark_idx++; // until next line } RPos pos = (*it)->getLocalPosition(); (*it)->setLocalPositionX(mstate->pen_x + pos.x + align_correct_x); (*it)->setLocalPositionY(mstate->pen_y + pos.y); // post composit event (*it)->onCachedCompositEnd(this, pen); } line_rect.pos.y = mstate->pen_y; // advance pen position mstate->pen_y -= (line_rect.size.h + getSpacing()); mstate->pen_x = 0; clear(); return line_rect; }
void whilePaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg) { switch (activeTool) { case TOOL_RUBBER: Replace(hdc, last.x, last.y, x, y, fg, bg, rubberRadius); break; case TOOL_PEN: Line(hdc, last.x, last.y, x, y, bg, 1); break; case TOOL_BRUSH: Brush(hdc, last.x, last.y, x, y, bg, brushStyle); break; case TOOL_AIRBRUSH: Airbrush(hdc, x, y, bg, airBrushWidth); break; case TOOL_LINE: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) roundTo8Directions(start.x, start.y, &x, &y); Line(hdc, start.x, start.y, x, y, bg, lineWidth); break; case TOOL_BEZIER: resetToU1(); pointStack[pointSP].x = x; pointStack[pointSP].y = y; switch (pointSP) { case 1: Line(hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, bg, lineWidth); break; case 2: Bezier(hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], bg, lineWidth); break; case 3: Bezier(hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], bg, lineWidth); break; } break; case TOOL_RECT: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) regularize(start.x, start.y, &x, &y); Rect(hdc, start.x, start.y, x, y, bg, fg, lineWidth, shapeStyle); break; case TOOL_SHAPE: resetToU1(); pointStack[pointSP].x = x; pointStack[pointSP].y = y; if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0)) roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y, &pointStack[pointSP].x, &pointStack[pointSP].y); if (pointSP + 1 >= 2) Poly(hdc, pointStack, pointSP + 1, bg, fg, lineWidth, shapeStyle, FALSE); break; case TOOL_ELLIPSE: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) regularize(start.x, start.y, &x, &y); Ellp(hdc, start.x, start.y, x, y, bg, fg, lineWidth, shapeStyle); break; case TOOL_RRECT: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) regularize(start.x, start.y, &x, &y); RRect(hdc, start.x, start.y, x, y, bg, fg, lineWidth, shapeStyle); break; } last.x = x; last.y = y; }
void endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg) { switch (activeTool) { case TOOL_FREESEL: { POINT *ptStackCopy; int i; rectSel_src[0] = rectSel_src[1] = 0x7fffffff; rectSel_src[2] = rectSel_src[3] = 0; for (i = 0; i <= ptSP; i++) { if (ptStack[i].x < rectSel_src[0]) rectSel_src[0] = ptStack[i].x; if (ptStack[i].y < rectSel_src[1]) rectSel_src[1] = ptStack[i].y; if (ptStack[i].x > rectSel_src[2]) rectSel_src[2] = ptStack[i].x; if (ptStack[i].y > rectSel_src[3]) rectSel_src[3] = ptStack[i].y; } rectSel_src[2] += 1 - rectSel_src[0]; rectSel_src[3] += 1 - rectSel_src[1]; rectSel_dest[0] = rectSel_src[0]; rectSel_dest[1] = rectSel_src[1]; rectSel_dest[2] = rectSel_src[2]; rectSel_dest[3] = rectSel_src[3]; if (ptSP != 0) { DeleteObject(hSelMask); hSelMask = CreateBitmap(rectSel_src[2], rectSel_src[3], 1, 1, NULL); DeleteObject(SelectObject(hSelDC, hSelMask)); ptStackCopy = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(POINT) * (ptSP + 1)); for (i = 0; i <= ptSP; i++) { ptStackCopy[i].x = ptStack[i].x - rectSel_src[0]; ptStackCopy[i].y = ptStack[i].y - rectSel_src[1]; } Poly(hSelDC, ptStackCopy, ptSP + 1, 0x00ffffff, 0x00ffffff, 1, 2, TRUE); HeapFree(GetProcessHeap(), 0, ptStackCopy); SelectObject(hSelDC, hSelBm = CreateDIBWithProperties(rectSel_src[2], rectSel_src[3])); resetToU1(); MaskBlt(hSelDC, 0, 0, rectSel_src[2], rectSel_src[3], hDrawingDC, rectSel_src[0], rectSel_src[1], hSelMask, 0, 0, MAKEROP4(SRCCOPY, WHITENESS)); Poly(hdc, ptStack, ptSP + 1, bg, bg, 1, 2, TRUE); newReversible(); MaskBlt(hDrawingDC, rectSel_src[0], rectSel_src[1], rectSel_src[2], rectSel_src[3], hSelDC, 0, 0, hSelMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND)); placeSelWin(); ShowWindow(hSelection, SW_SHOW); /* force refresh of selection contents */ SendMessage(hSelection, WM_LBUTTONDOWN, 0, 0); SendMessage(hSelection, WM_MOUSEMOVE, 0, 0); SendMessage(hSelection, WM_LBUTTONUP, 0, 0); } HeapFree(GetProcessHeap(), 0, ptStack); ptStack = NULL; break; } case TOOL_RECTSEL: resetToU1(); if ((rectSel_src[2] != 0) && (rectSel_src[3] != 0)) { DeleteObject(hSelMask); hSelMask = CreateBitmap(rectSel_src[2], rectSel_src[3], 1, 1, NULL); DeleteObject(SelectObject(hSelDC, hSelMask)); Rect(hSelDC, 0, 0, rectSel_src[2], rectSel_src[3], 0x00ffffff, 0x00ffffff, 1, 2); SelectObject(hSelDC, hSelBm = CreateDIBWithProperties(rectSel_src[2], rectSel_src[3])); resetToU1(); BitBlt(hSelDC, 0, 0, rectSel_src[2], rectSel_src[3], hDrawingDC, rectSel_src[0], rectSel_src[1], SRCCOPY); Rect(hdc, rectSel_src[0], rectSel_src[1], rectSel_src[0] + rectSel_src[2], rectSel_src[1] + rectSel_src[3], bgColor, bgColor, 0, TRUE); newReversible(); BitBlt(hDrawingDC, rectSel_src[0], rectSel_src[1], rectSel_src[2], rectSel_src[3], hSelDC, 0, 0, SRCCOPY); placeSelWin(); ShowWindow(hSelection, SW_SHOW); /* force refresh of selection contents */ SendMessage(hSelection, WM_LBUTTONDOWN, 0, 0); SendMessage(hSelection, WM_MOUSEMOVE, 0, 0); SendMessage(hSelection, WM_LBUTTONUP, 0, 0); } break; case TOOL_RUBBER: Erase(hdc, last.x, last.y, x, y, bg, rubberRadius); break; case TOOL_PEN: Line(hdc, last.x, last.y, x, y, fg, 1); SetPixel(hdc, x, y, fg); break; case TOOL_LINE: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) roundTo8Directions(start.x, start.y, &x, &y); Line(hdc, start.x, start.y, x, y, fg, lineWidth); break; case TOOL_BEZIER: pointSP++; if (pointSP == 4) pointSP = 0; break; case TOOL_RECT: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) regularize(start.x, start.y, &x, &y); Rect(hdc, start.x, start.y, x, y, fg, bg, lineWidth, shapeStyle); break; case TOOL_SHAPE: resetToU1(); pointStack[pointSP].x = x; pointStack[pointSP].y = y; if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0)) roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y, &pointStack[pointSP].x, &pointStack[pointSP].y); pointSP++; if (pointSP >= 2) { if ((pointStack[0].x - x) * (pointStack[0].x - x) + (pointStack[0].y - y) * (pointStack[0].y - y) <= lineWidth * lineWidth + 1) { Poly(hdc, pointStack, pointSP, fg, bg, lineWidth, shapeStyle, TRUE); pointSP = 0; } else { Poly(hdc, pointStack, pointSP, fg, bg, lineWidth, shapeStyle, FALSE); } } if (pointSP == 255) pointSP--; break; case TOOL_ELLIPSE: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) regularize(start.x, start.y, &x, &y); Ellp(hdc, start.x, start.y, x, y, fg, bg, lineWidth, shapeStyle); break; case TOOL_RRECT: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) regularize(start.x, start.y, &x, &y); RRect(hdc, start.x, start.y, x, y, fg, bg, lineWidth, shapeStyle); break; } }
void whilePaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg) { switch (activeTool) { case TOOL_FREESEL: if (ptSP == 0) newReversible(); ptSP++; if (ptSP % 1024 == 0) ptStack = HeapReAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, ptStack, sizeof(POINT) * (ptSP + 1024)); ptStack[ptSP].x = max(0, min(x, imgXRes)); ptStack[ptSP].y = max(0, min(y, imgYRes)); resetToU1(); Poly(hdc, ptStack, ptSP + 1, 0, 0, 2, 0, FALSE); break; case TOOL_RECTSEL: { POINT temp; resetToU1(); temp.x = max(0, min(x, imgXRes)); temp.y = max(0, min(y, imgYRes)); rectSel_dest[0] = rectSel_src[0] = min(start.x, temp.x); rectSel_dest[1] = rectSel_src[1] = min(start.y, temp.y); rectSel_dest[2] = rectSel_src[2] = max(start.x, temp.x) - min(start.x, temp.x); rectSel_dest[3] = rectSel_src[3] = max(start.y, temp.y) - min(start.y, temp.y); RectSel(hdc, start.x, start.y, temp.x, temp.y); break; } case TOOL_RUBBER: Erase(hdc, last.x, last.y, x, y, bg, rubberRadius); break; case TOOL_PEN: Line(hdc, last.x, last.y, x, y, fg, 1); break; case TOOL_BRUSH: Brush(hdc, last.x, last.y, x, y, fg, brushStyle); break; case TOOL_AIRBRUSH: Airbrush(hdc, x, y, fg, airBrushWidth); break; case TOOL_LINE: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) roundTo8Directions(start.x, start.y, &x, &y); Line(hdc, start.x, start.y, x, y, fg, lineWidth); break; case TOOL_BEZIER: resetToU1(); pointStack[pointSP].x = x; pointStack[pointSP].y = y; switch (pointSP) { case 1: Line(hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, fg, lineWidth); break; case 2: Bezier(hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], fg, lineWidth); break; case 3: Bezier(hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], fg, lineWidth); break; } break; case TOOL_RECT: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) regularize(start.x, start.y, &x, &y); Rect(hdc, start.x, start.y, x, y, fg, bg, lineWidth, shapeStyle); break; case TOOL_SHAPE: resetToU1(); pointStack[pointSP].x = x; pointStack[pointSP].y = y; if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0)) roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y, &pointStack[pointSP].x, &pointStack[pointSP].y); if (pointSP + 1 >= 2) Poly(hdc, pointStack, pointSP + 1, fg, bg, lineWidth, shapeStyle, FALSE); break; case TOOL_ELLIPSE: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) regularize(start.x, start.y, &x, &y); Ellp(hdc, start.x, start.y, x, y, fg, bg, lineWidth, shapeStyle); break; case TOOL_RRECT: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) regularize(start.x, start.y, &x, &y); RRect(hdc, start.x, start.y, x, y, fg, bg, lineWidth, shapeStyle); break; } last.x = x; last.y = y; }
void CScrollBar::CalcRects(int y /*= 0*/) { const int &cx = m_mdc.cx; const int &cy = m_mdc.cy; const int cxBtn = GetSystemMetrics(SM_CXHTHUMB); const int cyBtn = cxBtn + SCX(1); // Buttons m_rcBtn1 = RRect(0, 0, cxBtn, cyBtn); m_rcBtn2 = RRect(0, cy - cyBtn, cxBtn, cy); // Thumb m_rcThumb.x = 0; m_rcThumb.cx = cxBtn; int nFullRange = m_nRangeMax - m_nRangeMin + 1; int nVarRange = nFullRange - m_nPageSize; if (nVarRange <= 0) return; int cyFullRange = cy - 2 * cyBtn; m_rcThumb.cy = max((m_nPageSize * cyFullRange) / nFullRange, SCX(20)); int cyVarRange = cyFullRange - m_rcThumb.cy; if (cyVarRange <= 0) return; if (m_bDragging) { // Calculate virtual thumb position from mouse position and correct it m_rcThumb = m_rcDragging; m_rcThumb.y += y - m_ptDragging.y; if (m_rcThumb.y < cyBtn) m_rcThumb.y = cyBtn; if (m_rcThumb.bottom > cy - cyBtn) m_rcThumb.y -= m_rcThumb.bottom - (cy - cyBtn); // Calculate track position from virtual thumb position double dVarPos = (double)(m_rcThumb.y - cyBtn) / cyVarRange; int nTrackPos = m_nRangeMin + round(dVarPos * nVarRange); if (m_nTrackPos != nTrackPos) { m_nTrackPos = nTrackPos; PostMessage(GetParent(m_hWnd), WM_VSCROLL, MAKEWPARAM(SB_THUMBTRACK, m_nTrackPos), (LPARAM)m_hWnd); } // Calculate thumb position from track position m_rcThumb.y = cyBtn + round((double)((m_nTrackPos - m_nRangeMin) * cyVarRange) / nVarRange); } else { m_rcThumb.y = cyBtn + round((double)((m_nPos - m_nRangeMin) * cyVarRange) / nVarRange); // Calculate page up and down rectangles m_rcBtnPageUp = RRect(0, cyBtn, cxBtn, m_rcThumb.top); m_rcBtnPageDown = RRect(0, m_rcThumb.bottom, cxBtn, cy - cyBtn); } }
void endPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg) { switch (activeTool) { case TOOL_RUBBER: Replace(hdc, last.x, last.y, x, y, fg, bg, rubberRadius); break; case TOOL_PEN: Line(hdc, last.x, last.y, x, y, bg, 1); SetPixel(hdc, x, y, bg); break; case TOOL_LINE: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) roundTo8Directions(start.x, start.y, &x, &y); Line(hdc, start.x, start.y, x, y, bg, lineWidth); break; case TOOL_BEZIER: pointSP++; if (pointSP == 4) pointSP = 0; break; case TOOL_RECT: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) regularize(start.x, start.y, &x, &y); Rect(hdc, start.x, start.y, x, y, bg, fg, lineWidth, shapeStyle); break; case TOOL_SHAPE: resetToU1(); pointStack[pointSP].x = x; pointStack[pointSP].y = y; if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0)) roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y, &pointStack[pointSP].x, &pointStack[pointSP].y); pointSP++; if (pointSP >= 2) { if ((pointStack[0].x - x) * (pointStack[0].x - x) + (pointStack[0].y - y) * (pointStack[0].y - y) <= lineWidth * lineWidth + 1) { Poly(hdc, pointStack, pointSP, bg, fg, lineWidth, shapeStyle, TRUE); pointSP = 0; } else { Poly(hdc, pointStack, pointSP, bg, fg, lineWidth, shapeStyle, FALSE); } } if (pointSP == 255) pointSP--; break; case TOOL_ELLIPSE: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) regularize(start.x, start.y, &x, &y); Ellp(hdc, start.x, start.y, x, y, bg, fg, lineWidth, shapeStyle); break; case TOOL_RRECT: resetToU1(); if (GetAsyncKeyState(VK_SHIFT) < 0) regularize(start.x, start.y, &x, &y); RRect(hdc, start.x, start.y, x, y, bg, fg, lineWidth, shapeStyle); break; } }