void DisplayElement::InvalidateChild (DisplayElement *pChild, WebRect *pDirty) { WebRect dirty; dirty.Set(pDirty); dirty.Shift(mRect.left, mRect.top); if (GetOverflow() == DISPLAY_OVERFLOW_HIDDEN) { WebRect clipRect; GetClipRect(&clipRect); // If completely outside clipping rect, stop here if (!dirty.Overlaps(&clipRect)) { return; } // clip pDirty to our rect dirty.And(&clipRect); } if ((mFlags & DISPLAY_FLAG_FIXED_POS) || !mpParent) { DisplayManager *pManager = GetManager(); if (pManager) { if (mFlags & DISPLAY_FLAG_FIXED_POS) { dirty.Shift(pManager->mViewRect.left, pManager->mViewRect.top); } pManager->InvalidateViewportRegion(&dirty); } } else { mpParent->InvalidateChild(this, &dirty); } }
void WebEditBox::DrawThisOnly (DISPLAY_INT x, DISPLAY_INT y, WebGraphics *gc) { WebChar c; long line; WebRect box; GetFrameRect(&box); box.Shift(x,y); // gc->StartBuffer(); // begin buffering graphics commands gc->Rectangle(&box, GetBgColor(gc), GetBgColor(gc), 1); // draw background DrawFrame(&box, gc); // save the current graphics context clip rectangle and set clipping to the // text display region of the widget GetTextRect(&box); box.Shift(x,y); WebRect clipSave; gc->GetClip(&clipSave); if (clipSave.Overlaps(&box)) { WebRect clip(box); clip.And(&clipSave); gc->SetClip(&clip); miXOffset = (mpHScroll)? mpHScroll->GetPosition() : 0; miYOffset = (mpVScroll)? mpVScroll->GetPosition() : 0; // render our text WebFont font = mFont.GetFont(); if (mpText && font) { // this loop draws up to the last line for (line=0; line<(miNumLines-1); line++) { c = mpText[GetLineOffset(line+1)]; mpText[GetLineOffset(line+1)] = 0; DrawText(gc, box.left - miXOffset, box.top - miYOffset + (line * WEB_FONT_HEIGHT(font)), mpText + GetLineOffset(line), GetTextColor(gc), 0, 0, font); mpText[GetLineOffset(line+1)] = c; } // now draw the last line of text. DrawText(gc, box.left - miXOffset, box.top - miYOffset + (line*WEB_FONT_HEIGHT(font)), mpText + GetLineOffset(line), GetTextColor(gc), 0, 0, font); // if we have the focus, draw the cursor if ((mFlags & DISPLAY_FLAG_FOCUS) && !(mFlags & DISPLAY_FLAG_DISABLED)) { // now render the selected portion in reverse video (if we have one) if (mEditFlags & EDIT_FLAG_HAS_SELECTION) { long begin = EBSMIN(miCursorPos, miSelectBegin); long end = EBSMAX(miCursorPos, miSelectBegin); long beginLine = FindLine(begin), endLine = FindLine(end); DISPLAY_INT textLeft; long currentBegin, currentEnd; for (line=beginLine; line<=endLine; line++) { currentBegin = EBSMAX(begin, GetLineOffset(line)); if (line == endLine) { currentEnd = end; } else { currentEnd = EBSMIN(end, GetLineOffset(line+1)); } textLeft = gc->TextWidthLen(mpText + GetLineOffset(line), font, EBSMAX(0, begin - GetLineOffset(line))); c = mpText[currentEnd]; mpText[currentEnd] = 0; DrawText(gc, box.left - miXOffset + textLeft, box.top - miYOffset + (line*WEB_FONT_HEIGHT(font)), mpText + currentBegin, GetBgColor(gc), GetSelectColor(gc), 1, font); mpText[currentEnd] = c; } } DISPLAY_INT cursorX = box.left - miXOffset + gc->TextWidthLen(mpText + GetLineOffset(miCurrentLine), font, miCursorPos - GetLineOffset(miCurrentLine)) ; box.Set(cursorX, box.top - miYOffset + WEB_FONT_HEIGHT(font)*miCurrentLine, cursorX, box.top - miYOffset + WEB_FONT_HEIGHT(font)*(miCurrentLine+1)); gc->Rectangle(&box, GetSelectColor(gc), GetSelectColor(gc), 1); } } gc->SetClip(&clipSave); // restore the clip rectangle } // if clip overlaps /* if (mpVScroll && mpHScroll) { GetCornerRect(&box); box.Shift(x,y); gc->Rectangle(&box, LIGHTGRAY, LIGHTGRAY, 1); }*/ // gc->EndBuffer(); // send all buffered commands to the display }
void DisplayManager::UpdateScrollBuffer (void) { if ((GetManagerFlags() & MANAGER_FLAG_DIRTY) && mRoot.Get() && mScrollBuffer) { WebRect* dirty; ClearManagerFlag(MANAGER_FLAG_BUFFER_DIRTY); // move the dirty rectangle list onto the stack so it can't be corrupted vector dirtyListCopy = mDirtyList; mDirtyList.first = 0; mDirtyList.last = 0; vector_iterator vi; DISPLAY_INT viewWidth = mViewRect.Width(); DISPLAY_INT viewHeight = mViewRect.Height(); PresetWebRect viewCorner(&mViewRect); viewCorner.MoveTo(0,0); PresetWebRect bufferView(&mViewRect); bufferView.MoveTo(mViewRect.left % viewWidth, mViewRect.top % viewHeight); DISPLAY_INT bufferLeft = mViewRect.left - (mViewRect.left % viewWidth); DISPLAY_INT bufferTop = mViewRect.top - (mViewRect.top % viewHeight); dirty = (WebRect*) vector_get_first(&dirtyListCopy, &vi); while (dirty) { if (mViewRect.Overlaps(dirty)) { WebRect bufferDirty; bufferDirty.left = dirty->left - bufferLeft; bufferDirty.top = dirty->top - bufferTop; bufferDirty.SizeTo(dirty->Width(), dirty->Height()); bufferDirty.And(&bufferView); mScrollBuffer->SetClip(&bufferDirty); DISPLAY_INT x = mRoot.Get()->mRect.left - bufferLeft; DISPLAY_INT y = mRoot.Get()->mRect.top - bufferTop; mRoot.Get()->Draw (x, y, &bufferView, mScrollBuffer); PresetWebRect defaultClip(0, 0, viewWidth * 2 - 1, viewHeight * 2 - 1); mScrollBuffer->SetClip(&defaultClip); // copy bufferDirty 3 times, split if necessary PresetWebRect northwest (0, 0, viewWidth - 1, viewHeight - 1); PresetWebRect northeast (viewWidth, 0, viewWidth * 2 - 1, viewHeight - 1); PresetWebRect southeast (viewWidth, viewHeight, viewWidth * 2 - 1, viewHeight * 2 - 1); PresetWebRect southwest (0, viewHeight, viewWidth - 1, viewHeight * 2 - 1); if (bufferDirty.Overlaps(&northwest)) { PresetWebRect copyFrom (&bufferDirty); copyFrom.And(&northwest); PresetWebRect copyTo (©From); copyTo.ShiftOver(mViewRect.Width()); mScrollBuffer->CopyBufferRegion(©To, mScrollBuffer, copyFrom.left, copyFrom.top); copyTo.ShiftDown(mViewRect.Height()); mScrollBuffer->CopyBufferRegion(©To, mScrollBuffer, copyFrom.left, copyFrom.top); copyTo.ShiftOver(-mViewRect.Width()); mScrollBuffer->CopyBufferRegion(©To, mScrollBuffer, copyFrom.left, copyFrom.top); } if (bufferDirty.Overlaps(&northeast)) { PresetWebRect copyFrom (&bufferDirty); copyFrom.And(&northeast); PresetWebRect copyTo (©From); copyTo.ShiftDown(mViewRect.Height()); mScrollBuffer->CopyBufferRegion(©To, mScrollBuffer, copyFrom.left, copyFrom.top); copyTo.ShiftOver(-mViewRect.Width()); mScrollBuffer->CopyBufferRegion(©To, mScrollBuffer, copyFrom.left, copyFrom.top); copyTo.ShiftDown(-mViewRect.Height()); mScrollBuffer->CopyBufferRegion(©To, mScrollBuffer, copyFrom.left, copyFrom.top); } if (bufferDirty.Overlaps(&southeast)) { PresetWebRect copyFrom (&bufferDirty); copyFrom.And(&southeast); PresetWebRect copyTo (©From); copyTo.ShiftDown(-mViewRect.Height()); mScrollBuffer->CopyBufferRegion(©To, mScrollBuffer, copyFrom.left, copyFrom.top); copyTo.ShiftOver(-mViewRect.Width()); mScrollBuffer->CopyBufferRegion(©To, mScrollBuffer, copyFrom.left, copyFrom.top); copyTo.ShiftDown(mViewRect.Height()); mScrollBuffer->CopyBufferRegion(©To, mScrollBuffer, copyFrom.left, copyFrom.top); } if (bufferDirty.Overlaps(&southwest)) { PresetWebRect copyFrom (&bufferDirty); copyFrom.And(&southwest); PresetWebRect copyTo (©From); copyTo.ShiftDown(-mViewRect.Height()); mScrollBuffer->CopyBufferRegion(©To, mScrollBuffer, copyFrom.left, copyFrom.top); copyTo.ShiftOver(mViewRect.Width()); mScrollBuffer->CopyBufferRegion(©To, mScrollBuffer, copyFrom.left, copyFrom.top); copyTo.ShiftDown(mViewRect.Height()); mScrollBuffer->CopyBufferRegion(©To, mScrollBuffer, copyFrom.left, copyFrom.top); } } dirty = (WebRect*) vector_get_next(&vi); } // this ensures the dirty list is just the same as when we entered vector_delete(&mDirtyList); if (!this->GetManager()) { // if we're the root manager, we'll need this list in a sec. mDirtyList = dirtyListCopy; } else { ClearManagerFlag(MANAGER_FLAG_DIRTY); vector_delete(&dirtyListCopy); } } }
void DisplayManager::DrawThisOnly (DISPLAY_INT x, DISPLAY_INT y, WebGraphics *gc) { DISPLAY_INT scrollLeft = (mpHScroll)? mpHScroll->GetPosition() : mViewRect.left; DISPLAY_INT scrollTop = (mpVScroll)? mpVScroll->GetPosition() : mViewRect.top; mViewRect.MoveTo(scrollLeft, scrollTop); WebRect padding; GetPaddingWidth(&padding); // find our viewport rect in screen coordinates WebRect screenRect(mRect); screenRect.MoveTo(x,y); WebRect screenView(screenRect); screenView.Shift(padding.left, padding.top); screenView.SizeTo(mViewRect.Width(), mViewRect.Height()); WebRect saveClip; gc->GetClip(&saveClip); WebRect screenDirty(screenView); if (saveClip.Overlaps(&screenDirty)) { screenDirty.And(&saveClip); #ifdef WEBC_BUFFER_SCROLLING if ((GetManagerFlags() & MANAGER_FLAG_BUFFER_SCROLL) && mScrollBuffer) { if (GetManagerFlags() & MANAGER_FLAG_BUFFER_DIRTY) { UpdateScrollBuffer(); } // instead of invoking the Draw method of mRoot, just copy the contents of the // buffer at this location. gc->CopyBufferRegion ( &screenDirty, mScrollBuffer, screenDirty.left - screenView.left + (mViewRect.left % mViewRect.Width()), screenDirty.top - screenView.top + (mViewRect.top % mViewRect.Height())); } else { #endif gc->SetClip(&screenDirty); if (mRoot.Get()) { mRoot.Get()->Draw(screenView.left + mRoot.Get()->mRect.left - scrollLeft, screenView.top + mRoot.Get()->mRect.top - scrollTop, &screenView, gc); } #ifdef WEBC_BUFFER_SCROLLING } #endif gc->SetClip(&saveClip); } // draw the little gray rectangle if (mpVScroll && mpHScroll && webc_GetDefaultBoolean(WEBC_DEFAULT_DRAW_SCROLL_CORNER)) { WebRect box; WebColor c = gc->RGBToColor(webc_GetDefaultColor(WEBC_DEFAULT_SCROLL_CORNER_COLOR)); box.SetSizeAndPosition(screenView.right + 1, screenView.bottom + 1, mpVScroll->Width(), mpHScroll->Height()); gc->Rectangle(&box, c, c, 1); } }
void DisplayManager::Draw(DISPLAY_INT x, DISPLAY_INT y, WebRect *pViewport, WebGraphics *pGC) { if (mNoRefresh) { DisplayManager* parentDisplayManager = GetManager(); if (parentDisplayManager) { // This handles the case where a DisplayManager that is NOT the root // DisplayManager has a positive refresh lock, prohibiting its being // drawn, but the parent DisplayManager does not (otherwise we would // not even be in our Draw method); in this case: // // IF this element is within the collective invalid region being // painted, THEN we want to re-invalidate the invalid part of (this), // which will cause said region to re-paint when the refresh lock // is removed from this element and this->Refresh is eventually called. WebRect clipRect; pGC->GetClip(&clipRect); WebRect screenRect(mRect); screenRect.MoveTo(x,y); if (clipRect.Overlaps(&screenRect)) { SetManagerFlag(MANAGER_FLAG_TRIED_TO_DRAW); //screenRect.And(&clipRect); //screenRect.Shift(-pViewport->left, -pViewport->top); //parentDisplayManager->InvalidateViewportRegion(&screenRect); } } return; } FormatResult result; switch (GetScrollMode()) { case SCROLL_MODE_NONE: if (mpVScroll || mpHScroll) { DetachVScroll(); DetachHScroll(); UpdateViewport(); } break; case SCROLL_MODE_HSCROLL: if (mpVScroll || !mpHScroll) { DetachVScroll(); AttachHScroll(); UpdateViewport(); } break; case SCROLL_MODE_VSCROLL: if (!mpVScroll || mpHScroll) { AttachVScroll(); DetachHScroll(); UpdateViewport(); } break; case SCROLL_MODE_BOTH: if (!mpVScroll || !mpHScroll) { AttachVScroll(); AttachHScroll(); UpdateViewport(); } break; case SCROLL_MODE_AUTO: break; } if (mRoot.Get()) { int i = 0; do { result = mRoot.Get()->FormatForViewport(&mViewRect, (mpHScroll != 0), (mpVScroll != 0)); if (GetScrollMode() == SCROLL_MODE_AUTO) { if (result == DISPLAY_FORMAT_NEEDS_VSCROLL) { // create a vscroll bar if (mpVScroll) { // what the... we already have a vscroll bar! break; } AttachVScroll(); // check for creation failure - may indicate low memory condition if (!mpVScroll) { // can't go on... break; } UpdateViewport(); } else if (result == DISPLAY_FORMAT_NEEDS_HSCROLL) { // create a hscroll bar if (mpHScroll) { // what the... we already have a hscroll bar! break; } AttachHScroll(); // check for creation failure - may indicate low memory condition if (!mpHScroll) { // can't go on... break; } UpdateViewport(); } } else { break; } // put a hard upper bound on the number of times we try to re-format // (4, since this means we've covered all combinations of horizontal // and vertical scroll bars on the window) i++; } while (result != DISPLAY_FORMAT_SUCCESS && i < 5); if (GetScrollMode() == SCROLL_MODE_AUTO) { WebRect rootBounds; GetRootBounds(&rootBounds); if (rootBounds.Height() <= mViewRect.Height() && mpVScroll) { DetachVScroll(); UpdateViewport(); mRoot.Get()->FormatForViewport(&mViewRect, (mpHScroll != 0), (mpVScroll != 0)); GetRootBounds(&rootBounds); } if (rootBounds.Width() <= mViewRect.Width() && mpHScroll) { DetachHScroll(); UpdateViewport(); mRoot.Get()->FormatForViewport(&mViewRect, (mpHScroll != 0), (mpVScroll != 0)); GetRootBounds(&rootBounds); } if (rootBounds.Height() <= mViewRect.Height() && mpVScroll) { DetachVScroll(); UpdateViewport(); mRoot.Get()->FormatForViewport(&mViewRect, (mpHScroll != 0), (mpVScroll != 0)); GetRootBounds(&rootBounds); } } mViewportChanged = WEBC_FALSE; CorrectViewportPosition(); if (mpFocus && (mpVScroll!=0) && (mpHScroll!=0)) { WebRect focusRect; WebRect elemRect; WEBC_BOOL ensureFocusVisible = mpFocus->GetFocusRect (&focusRect); if (ensureFocusVisible) { GetElementRect(&elemRect, mpFocus); focusRect.Shift(elemRect.left, elemRect.top); // this will adjust the scroll bars so that the given rect is in view EnsureRectVisible(&focusRect); } } } DisplayElement::Draw(x, y, pViewport, pGC); }