void WebViewHost::paintInvalidatedRegion() { #if ENABLE(REQUEST_ANIMATION_FRAME) webWidget()->animate(0.0); #endif webWidget()->layout(); WebSize widgetSize = webWidget()->size(); WebRect clientRect(0, 0, widgetSize.width, widgetSize.height); // Paint the canvas if necessary. Allow painting to generate extra rects // for the first two calls. This is necessary because some WebCore rendering // objects update their layout only when painted. // Store the total area painted in total_paint. Then tell the gdk window // to update that area after we're done painting it. for (int i = 0; i < 3; ++i) { // rect = intersect(proxy()->paintRect() , clientRect) WebRect damageRect = proxy()->paintRect(); int left = max(damageRect.x, clientRect.x); int top = max(damageRect.y, clientRect.y); int right = min(damageRect.x + damageRect.width, clientRect.x + clientRect.width); int bottom = min(damageRect.y + damageRect.height, clientRect.y + clientRect.height); WebRect rect; if (left < right && top < bottom) rect = WebRect(left, top, right - left, bottom - top); proxy()->setPaintRect(WebRect()); if (rect.isEmpty()) continue; paintRect(rect); } ASSERT(proxy()->paintRect().isEmpty()); }
void DisplayElement::GetBounds (WebRect *rect) { if (mFlags & DISPLAY_FLAG_BOUNDS_VALID) { *rect = mBounds; return; } *rect = mRect; WebRect childRect; DisplayElement *pChild = mpFirstChild; while (pChild) { if (!(pChild->mFlags & DISPLAY_FLAG_FIXED_POS)) { pChild->GetBounds(&childRect); childRect.Shift(mRect.left, mRect.top); rect->Or(&childRect); } pChild = pChild->mpNext; } SetFlag(DISPLAY_FLAG_BOUNDS_VALID); mBounds = *rect; }
/*---------------------------------------------------------------------------*/ void HTMLBodyDisplay::Draw (DISPLAY_INT x, DISPLAY_INT y, WebRect *pViewport, WebGraphics *pGC) { FormatIfNecessary(); #if (WEBC_SUPPORT_FRAMES) if (mpFrameSet) { mpFrameSet->Draw(x, y, pViewport, pGC); } else #endif // WEBC_SUPPORT_FRAMES { if (!(mpHtmlElement->mFlags & HBODY_FLAG_NOBACKGROUND)) { WebRect screenRect; screenRect.Set(x, y, pViewport->right, pViewport->bottom); DrawBackground(&screenRect, pViewport, pGC); } // Draw all children DisplayElement *pChild = mpFirstChild; while (pChild) { if (pChild->mFlags & DISPLAY_FLAG_FIXED_POS) { pChild->Draw(pViewport->left + pChild->mRect.left, pViewport->top + pChild->mRect.top, pViewport, pGC); } else { pChild->Draw(x + pChild->mRect.left, y + pChild->mRect.top, pViewport, pGC); } pChild = pChild->mpNext; } } }
int HTMLString::GetDocumentDisplayRect (WebRect *rect, int n) { WebRect displayRect; HTMLStringDisplay *display = mpFirstDisplay; while (display && n > 0) { if (display->GetStringIndex() + display->GetStringLength() >= miLength) { display = 0; break; } n--; display = display->GetNextSubString(); } if (display) { displayRect.Set(&display->mRect); if (display->mpParent) { DISPLAY_INT x, y; display->mpParent->GetDisplayPosition(display, &x, &y); displayRect.MoveTo(x,y); } rect->Set(&displayRect); return (0); } return (-1); }
void DisplayManager::CorrectViewportPosition (void) { if (mRoot.Get()) { WebRect bounds; PresetWebRect rect(&mViewRect); GetRootBounds(&bounds); rect.MoveTo(0,0); bounds.Or(&rect); if (mViewRect.left < bounds.left) { mViewRect.Shift(bounds.left - mViewRect.left, 0); } if (mViewRect.right > bounds.right) { mViewRect.Shift(bounds.right - mViewRect.right, 0); } if (mViewRect.top < bounds.top) { mViewRect.Shift(0, bounds.top - mViewRect.top); } if (mViewRect.bottom > bounds.bottom) { mViewRect.Shift(0, bounds.bottom - mViewRect.bottom); } if (mpVScroll) { // Range and Window must be set BEFORE Position, // so position is not unjustly clipped! mpVScroll->SetRange(bounds.Height()); mpVScroll->SetWindow(mViewRect.Height()); mpVScroll->SetPosition(mViewRect.top); } if (mpHScroll) { // Range and Window must be set BEFORE Position, // so position is not unjustly clipped! mpHScroll->SetRange(bounds.Width()); mpHScroll->SetWindow(mViewRect.Width()); mpHScroll->SetPosition(mViewRect.left); } } }
void WebListBox::ResizeScrollBars(void) { if (mpHScroll) { WebRect r; r.Set(GetMargin() + GetBorder(), Height() - GetMargin() - GetBorder() - miSliderWidth - 1, Width() - (mpVScroll ? miSliderWidth : 0) - GetMargin() - GetBorder() - 1, Height() - GetMargin() - GetBorder() - 1); mpHScroll->Move(&r); WebRect vr; GetOptionsRect(&vr); mpHScroll->SetWindow(vr.Width()); mpHScroll->Invalidate(); } if (mpVScroll) { WebRect r; r.Set(Width() - 1 - GetMargin() - GetBorder() - miSliderWidth, GetMargin() + GetBorder(), Width() - 1 - GetMargin() - GetBorder(), Height() - 1 - (mpHScroll ? miSliderWidth : 0) - GetMargin() - GetBorder()); mpVScroll->Move(&r); WebRect vr; GetOptionsRect(&vr); mpVScroll->SetWindow(vr.Height()); mpVScroll->Invalidate(); } }
void WebPopupMenuImpl::paint(WebCanvas* canvas, const WebRect& rect) { if (!m_widget) return; if (!rect.isEmpty()) m_widget->paint(&GraphicsContextBuilder(canvas).context(), rect); }
void WebPopupMenuImpl::paintContents(WebCanvas* canvas, const WebRect& rect, bool, WebFloatRect&) { if (!m_widget) return; if (!rect.isEmpty()) { GraphicsContext context(canvas); m_widget->paint(&context, rect); } }
void DisplayManager::UpdateViewport (void) { WebRect view; WebRect padding; WebRect vscrollRect; WebRect hscrollRect; GetPaddingWidth(&padding); view.Set (mRect.left + padding.left, mRect.top + padding.top, mRect.right - padding.right, mRect.bottom - padding.bottom); if (mpVScroll) { vscrollRect.Set (mRect.Width() - padding.right - webc_GetDefaultDisplayInt(WEBC_DEFAULT_SLIDER_WIDTH), padding.top, mRect.Width() - 1 - padding.right, mRect.Height() - 1 - padding.bottom); view.right -= webc_GetDefaultDisplayInt(WEBC_DEFAULT_SLIDER_WIDTH); if (mpHScroll) { hscrollRect.Set (padding.left, mRect.Height() - padding.bottom - webc_GetDefaultDisplayInt(WEBC_DEFAULT_SLIDER_WIDTH), mRect.Width() - padding.right - webc_GetDefaultDisplayInt(WEBC_DEFAULT_SLIDER_WIDTH), mRect.Height() - 1 - padding.bottom); vscrollRect.bottom -= webc_GetDefaultDisplayInt(WEBC_DEFAULT_SLIDER_WIDTH) - 1; view.bottom -= webc_GetDefaultDisplayInt(WEBC_DEFAULT_SLIDER_WIDTH); mpHScroll->Move(&hscrollRect); } mpVScroll->Move(&vscrollRect); } else { if (mpHScroll) { hscrollRect.Set (padding.left, mRect.Height() - padding.bottom - webc_GetDefaultDisplayInt(WEBC_DEFAULT_SLIDER_WIDTH), mRect.Width() - 1 - padding.right, mRect.Height() - 1 - padding.bottom); view.bottom -= webc_GetDefaultDisplayInt(WEBC_DEFAULT_SLIDER_WIDTH); mpHScroll->Move(&hscrollRect); } } view.MoveTo(mViewRect.left, mViewRect.top); SetViewport(&view); }
FormatResult HTMLBodyDisplay::FormatForViewport ( WebRect* viewportRect, WEBC_BOOL hscrollPresent, WEBC_BOOL vscrollPresent ) { if (Width() != viewportRect->Width()) { SizeTo(viewportRect->Width(), viewportRect->Height()); SetParentStyleModified(); } else if (Height() != viewportRect->Height()) { SizeTo(viewportRect->Width(), viewportRect->Height()); SetPosChildStyleModified(); } FormatIfNecessary(); CSSPropertyValue overflowValue; if (mpHtmlElement->GetStyleFromCSS(CSS_PROPERTY_OVERFLOW, &overflowValue) == CSS_VALUE_SPECIFIED) { if (CSS_OVERFLOW_HIDDEN == overflowValue.overflow) { return (DISPLAY_FORMAT_SUCCESS); } } #if (WEBC_SUPPORT_SCROLLBARS) WebRect bounds; GetBounds(&bounds); if (bounds.Height() > viewportRect->Height() && !vscrollPresent) { return (DISPLAY_FORMAT_NEEDS_VSCROLL); } if (bounds.Width() > viewportRect->Width() && !hscrollPresent) { return (DISPLAY_FORMAT_NEEDS_HSCROLL); } #endif return (DISPLAY_FORMAT_SUCCESS); }
void WebPopupMenuImpl::paint(WebCanvas* canvas, const WebRect& rect, PaintOptions) { if (!m_widget) return; if (!rect.isEmpty()) { GraphicsContext context(canvas); context.applyDeviceScaleFactor(m_client->deviceScaleFactor()); m_widget->paint(&context, rect); } }
void WebPopupMenuImpl::paintContents(WebCanvas* canvas, const WebRect& rect, bool, WebContentLayerClient::GraphicsContextStatus contextStatus) { if (!m_widget) return; if (!rect.isEmpty()) { GraphicsContext context(canvas, contextStatus == WebContentLayerClient::GraphicsContextEnabled ? GraphicsContext::NothingDisabled : GraphicsContext::FullyDisabled); m_widget->paint(&context, rect); } }
void WebPopupMenuImpl::paint(WebCanvas* canvas, const WebRect& rect) { if (!m_widget) return; if (!rect.isEmpty()) { OwnPtr<GraphicsContext> context = GraphicsContext::deprecatedCreateWithCanvas(canvas); float scaleFactor = m_client->deviceScaleFactor(); context->scale(scaleFactor, scaleFactor); m_widget->paint(context.get(), rect); } }
void WebListBox::FitSelection(void) { if (UseVScroll()) { DISPLAY_INT offsetX, offsetY; WebRect r; GetScrollOffset(&offsetX, &offsetY); GetOptionsRect(&r); int pos = miSelected * (miTextHeight + GetSpacing()); if (pos < offsetY) { mpVScroll->SetPosition(pos); } else if (pos > offsetY + r.Height() - miTextHeight - GetSpacing()) { mpVScroll->SetPosition(pos - r.Height() + miTextHeight + GetSpacing()); } } }
void WebViewHost::updatePaintRect(const WebRect& rect) { // m_paintRect = m_paintRect U rect if (rect.isEmpty()) return; if (m_paintRect.isEmpty()) { m_paintRect = rect; return; } int left = min(m_paintRect.x, rect.x); int top = min(m_paintRect.y, rect.y); int right = max(m_paintRect.x + m_paintRect.width, rect.x + rect.width); int bottom = max(m_paintRect.y + m_paintRect.height, rect.y + rect.height); m_paintRect = WebRect(left, top, right - left, bottom - top); }
void PageWidgetDelegate::paint(Page* page, PageOverlayList* overlays, WebCanvas* canvas, const WebRect& rect, CanvasBackground background) { if (rect.isEmpty()) return; GraphicsContextBuilder builder(canvas); GraphicsContext& gc = builder.context(); gc.platformContext()->setDrawingToImageBuffer(background == Opaque ? false : true); gc.applyDeviceScaleFactor(page->deviceScaleFactor()); IntRect dirtyRect(rect); gc.save(); FrameView* view = mainFrameView(page); // FIXME: Can we remove the mainFrame()->document() check? if (view && page->mainFrame()->document()) { gc.clip(dirtyRect); view->paint(&gc, dirtyRect); if (overlays) overlays->paintWebFrame(gc); } else gc.fillRect(dirtyRect, Color::white, ColorSpaceDeviceRGB); gc.restore(); }
void PageWidgetDelegate::paint(Page* page, PageOverlayList* overlays, WebCanvas* canvas, const WebRect& rect, CanvasBackground background) { if (rect.isEmpty()) return; GraphicsContext gc(canvas); gc.setCertainlyOpaque(background == Opaque); gc.applyDeviceScaleFactor(page->deviceScaleFactor()); gc.setUseHighResMarkers(page->deviceScaleFactor() > 1.5f); IntRect dirtyRect(rect); gc.save(); // Needed to save the canvas, not the GraphicsContext. FrameView* view = mainFrameView(page); // FIXME: Can we remove the mainFrame()->document() check? if (view && page->mainFrame()->document()) { gc.clip(dirtyRect); view->paint(&gc, dirtyRect); if (overlays) overlays->paintWebFrame(gc); } else { gc.fillRect(dirtyRect, Color::white); } gc.restore(); }
void PageWidgetDelegate::paint(Page& page, PageOverlayList* overlays, WebCanvas* canvas, const WebRect& rect, CanvasBackground background, LocalFrame& root) { if (rect.isEmpty()) return; GraphicsContext gc(canvas, nullptr); gc.setCertainlyOpaque(background == Opaque); float scaleFactor = page.deviceScaleFactor(); gc.scale(scaleFactor, scaleFactor); gc.setDeviceScaleFactor(scaleFactor); IntRect dirtyRect(rect); gc.save(); // Needed to save the canvas, not the GraphicsContext. FrameView* view = root.view(); if (view) { gc.clip(dirtyRect); view->paint(&gc, dirtyRect); if (overlays) overlays->paintWebFrame(gc); } else { gc.fillRect(dirtyRect, Color::white); } gc.restore(); }
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 TestShell::dump() { WebScriptController::flushConsoleMessages(); // Dump the requested representation. WebFrame* frame = m_webView->mainFrame(); if (!frame) return; bool shouldDumpAsText = m_layoutTestController->shouldDumpAsText(); bool shouldDumpAsAudio = m_layoutTestController->shouldDumpAsAudio(); bool shouldGeneratePixelResults = m_layoutTestController->shouldGeneratePixelResults(); bool shouldDumpAsPrinted = m_layoutTestController->isPrinting(); bool dumpedAnything = false; if (shouldDumpAsAudio) { m_printer->handleAudioHeader(); const WebKit::WebArrayBufferView& webArrayBufferView = m_layoutTestController->audioData(); printf("Content-Length: %d\n", webArrayBufferView.byteLength()); if (fwrite(webArrayBufferView.baseAddress(), 1, webArrayBufferView.byteLength(), stdout) != webArrayBufferView.byteLength()) FATAL("Short write to stdout, disk full?\n"); printf("\n"); m_printer->handleTestFooter(true); fflush(stdout); fflush(stderr); return; } if (m_params.dumpTree) { dumpedAnything = true; m_printer->handleTextHeader(); // Text output: the test page can request different types of output // which we handle here. if (!shouldDumpAsText) { // Plain text pages should be dumped as text string mimeType = frame->dataSource()->response().mimeType().utf8(); if (mimeType == "text/plain") { shouldDumpAsText = true; shouldGeneratePixelResults = false; } } if (shouldDumpAsText) { bool recursive = m_layoutTestController->shouldDumpChildFramesAsText(); string dataUtf8 = shouldDumpAsPrinted ? dumpFramesAsPrintedText(frame, recursive) : dumpFramesAsText(frame, recursive); if (fwrite(dataUtf8.c_str(), 1, dataUtf8.size(), stdout) != dataUtf8.size()) FATAL("Short write to stdout, disk full?\n"); } else { WebFrame::RenderAsTextControls renderTextBehavior = WebFrame::RenderAsTextNormal; if (shouldDumpAsPrinted) renderTextBehavior |= WebFrame::RenderAsTextPrinting; if (m_params.debugRenderTree) renderTextBehavior |= WebFrame::RenderAsTextDebug; printf("%s", frame->renderTreeAsText(renderTextBehavior).utf8().data()); bool recursive = m_layoutTestController->shouldDumpChildFrameScrollPositions(); dumpFrameScrollPosition(frame, recursive); } if (m_layoutTestController->shouldDumpBackForwardList()) printf("%s", dumpAllBackForwardLists().c_str()); } if (dumpedAnything && m_params.printSeparators) m_printer->handleTextFooter(); if (m_params.dumpPixels && shouldGeneratePixelResults) { // Image output: we write the image data to the file given on the // command line (for the dump pixels argument), and the MD5 sum to // stdout. dumpedAnything = true; m_webView->layout(); if (m_layoutTestController->testRepaint()) { WebSize viewSize = m_webView->size(); int width = viewSize.width; int height = viewSize.height; if (m_layoutTestController->sweepHorizontally()) { for (WebRect column(0, 0, 1, height); column.x < width; column.x++) m_webViewHost->paintRect(column); } else { for (WebRect line(0, 0, width, 1); line.y < height; line.y++) m_webViewHost->paintRect(line); } } else if (m_layoutTestController->isPrinting()) m_webViewHost->paintPagesWithBoundaries(); else m_webViewHost->paintInvalidatedRegion(); // See if we need to draw the selection bounds rect. Selection bounds // rect is the rect enclosing the (possibly transformed) selection. // The rect should be drawn after everything is laid out and painted. if (m_layoutTestController->shouldDumpSelectionRect()) { // If there is a selection rect - draw a red 1px border enclosing rect WebRect wr = frame->selectionBoundsRect(); if (!wr.isEmpty()) { // Render a red rectangle bounding selection rect SkPaint paint; paint.setColor(0xFFFF0000); // Fully opaque red paint.setStyle(SkPaint::kStroke_Style); paint.setFlags(SkPaint::kAntiAlias_Flag); paint.setStrokeWidth(1.0f); SkIRect rect; // Bounding rect rect.set(wr.x, wr.y, wr.x + wr.width, wr.y + wr.height); m_webViewHost->canvas()->drawIRect(rect, paint); } } dumpImage(m_webViewHost->canvas()); } m_printer->handleImageFooter(); m_printer->handleTestFooter(dumpedAnything); fflush(stdout); fflush(stderr); }
void WebListBox::SetupScrollBars(WebGraphics * gc) { WebRect window; GetContentRect(&window); DISPLAY_INT w = window.Width(); DISPLAY_INT h = window.Height(); WEBC_BOOL needH, needV; needH = needV = WEBC_FALSE; for (int t = 0; t < 2; t++) { if (w < GetTotalTextWidth()) { needH = WEBC_TRUE; h -= miSliderWidth; } if (h < GetTotalTextHeight()) { needV = WEBC_TRUE; w -= miSliderWidth; } } if (needH && !mpHScroll) { WEBC_NEW_VERBOSE(mpHScroll, WebHScroll,"wtlist:WebVscroll"); if (mpHScroll) { mpHScroll->SetListener(this); mpHScroll->SetRange(GetTotalTextWidth()); mpHScroll->SetStep(miTextHeight); mpHScroll->SetPosition(0); if (mFlags & DISPLAY_FLAG_DISABLED) { mpHScroll->Disable(); } InsertLast(mpHScroll); ResizeScrollBars(); } } else if (!needH && mpHScroll) { Remove(mpHScroll); WEBC_DELETE(mpHScroll); mpHScroll = WEBC_NULL; } if (needV && !mpVScroll) { WEBC_NEW_VERBOSE(mpVScroll, WebVScroll,"Wtlist:WebVscroll"); if (mpVScroll) { mpVScroll->SetListener(this); mpVScroll->SetRange(GetTotalTextHeight()); mpVScroll->SetStep(miTextHeight + GetSpacing()); mpVScroll->SetPosition(0); if (mFlags & DISPLAY_FLAG_DISABLED) { mpVScroll->Disable(); } InsertLast(mpVScroll); ResizeScrollBars(); } } else if (!needV && mpVScroll) { Remove(mpVScroll); WEBC_DELETE(mpVScroll); mpVScroll = WEBC_NULL; } }
/*---------------------------------------------------------------------------*/ template<class T> IPositionedFormatContext* HTMLElementDisplay<T>::FormatSelfPositioned ( DisplayElement* displayParent, IPositionedFormatContext* rootContext, IPositionedFormatContext* parentContext, FormatContextFactory* childContextFactory, WEBC_BOOL generateChildContext ) { WebRect rect; WEBC_UINT16 position = GetPosition(); IPositionedFormatContext* childContext = 0; if (position == TU_POSITION_RELATIVE) { if (generateChildContext) { const WebRect * tmpRect = &(((DisplayElement *)(this))->mRect); rect.Set(tmpRect); rect.MoveTo(0,0); CSSLength height; GetCSSLength(&height, CSS_PROPERTY_HEIGHT); childContext = childContextFactory->newPositioned ( &rect, (height.type == CSS_LENGTH_UNIT_AUTO) || (height.type == CSS_LENGTH_UNIT_PERCENT && parentContext->parentHeightIsAuto()), // parent height is auto TU_DIR_LTR, 0, // border-left-width 0, // border-top-width 0, // border-right-width 0, // border-bottom-width 0, // autoIndentLeft 0, // autoIndentTop 0 // autoIndentRight ); } } else { WebRect containingBlock; IPositionedFormatContext* containingContext; DISPLAY_INT borderLeftValue; DISPLAY_INT borderTopValue; DISPLAY_INT borderRightValue; DISPLAY_INT borderBottomValue; if (displayParent) { if (displayParent != T::mpParent) { mHtmlElementDisplayFlags &= ~HELEM_DISPLAY_FLAG_STYLE_SET; } displayParent->InsertOrdered(this); } if (position == TU_POSITION_FIXED) { T::SetFixedPosition(WEBC_TRUE); containingContext = rootContext; } else { T::SetFixedPosition(WEBC_FALSE); containingContext = parentContext; } containingContext->getContainingBlock(&containingBlock); WEBC_BOOL parentHeightIsAuto = containingContext->parentHeightIsAuto(); int textDirection = containingContext->getTextDirection(); DISPLAY_INT parentBorderLeft = containingContext->getParentBorderLeft(); DISPLAY_INT parentBorderTop = containingContext->getParentBorderTop(); DISPLAY_INT parentBorderRight = containingContext->getParentBorderRight(); DISPLAY_INT parentBorderBottom = containingContext->getParentBorderBottom(); DISPLAY_INT autoIndentLeft = parentContext->getAutoIndentLeft(); DISPLAY_INT autoIndentTop = parentContext->getAutoIndentTop(); DISPLAY_INT autoIndentRight = parentContext->getAutoIndentRight(); if (position == TU_POSITION_FIXED) { WebRect parentRect; parentContext->getContainingBlock(&parentRect); autoIndentLeft += parentRect.left; autoIndentTop += parentRect.top; autoIndentRight += (containingBlock.right - parentRect.right); } DISPLAY_INT parentWidth = containingBlock.Width() - (parentBorderLeft + parentBorderRight); DISPLAY_INT parentHeight = containingBlock.Height() - (parentBorderTop + parentBorderBottom); WebFont font = mpHtmlElement->GetWebFont(); DISPLAY_INT emHeight = font? WEB_FONT_HEIGHT(font) : WEBC_CFG_DEFAULT_TEXT_HEIGHT; DISPLAY_INT exHeight = emHeight >> 1; // First find the left edge and width CSSLength left; CSSLength right; CSSLength width; // Find value for left, right, width, marginLeft, marginRight GetCSSLength(&left, CSS_PROPERTY_LEFT); GetCSSLength(&right, CSS_PROPERTY_RIGHT); GetCSSLength(&width, CSS_PROPERTY_WIDTH); DISPLAY_INT leftValue; DISPLAY_INT rightValue; DISPLAY_INT widthValue; DISPLAY_INT marginLeftValue; DISPLAY_INT paddingLeftValue; DISPLAY_INT paddingTopValue; DISPLAY_INT paddingRightValue; DISPLAY_INT paddingBottomValue; // Find value for padding and border paddingLeftValue = GetPixelLength(CSS_PROPERTY_PADDING_LEFT, parentWidth, emHeight, exHeight, 0); paddingTopValue = GetPixelLength(CSS_PROPERTY_PADDING_TOP, parentWidth, emHeight, exHeight, 0); paddingRightValue = GetPixelLength(CSS_PROPERTY_PADDING_RIGHT, parentWidth, emHeight, exHeight, 0); paddingBottomValue = GetPixelLength(CSS_PROPERTY_PADDING_BOTTOM, parentWidth, emHeight, exHeight, 0); borderLeftValue = GetBorderWidth(CSS_LEFT, parentWidth, emHeight, exHeight, parentBorderLeft); borderTopValue = GetBorderWidth(CSS_TOP, parentWidth, emHeight, exHeight, parentBorderTop); borderRightValue = GetBorderWidth(CSS_RIGHT, parentWidth, emHeight, exHeight, parentBorderRight); borderBottomValue = GetBorderWidth(CSS_BOTTOM, parentWidth, emHeight, exHeight, parentBorderBottom); CSSLength height; CSSLength top; CSSLength bottom; DISPLAY_INT heightValue=0; WEBC_BOOL heightIsAuto=0; GetCSSLength(&height, CSS_PROPERTY_HEIGHT); GetCSSLength(&top, CSS_PROPERTY_TOP); #define NOTHING_KNOWN 0 #define HEIGHT_KNOWN 1 #define TOP_KNOWN 2 #define BOTTOM_KNOWN 4 WEBC_UINT8 verticalCase; verticalCase = (height.type == CSS_LENGTH_UNIT_AUTO || (height.type == CSS_LENGTH_UNIT_PERCENT && parentHeightIsAuto))? 0 : HEIGHT_KNOWN; verticalCase |= (top.type == CSS_LENGTH_UNIT_AUTO)? 0 : TOP_KNOWN; if (verticalCase != (HEIGHT_KNOWN|TOP_KNOWN)) { GetCSSLength(&bottom, CSS_PROPERTY_BOTTOM); verticalCase |= (bottom.type == CSS_LENGTH_UNIT_AUTO || parentHeightIsAuto)? 0 : BOTTOM_KNOWN; } DISPLAY_INT topValue = 0; DISPLAY_INT bottomValue = 0; DISPLAY_INT marginTopValue = 0; DISPLAY_INT marginBottomValue = 0; switch (verticalCase) { case NOTHING_KNOWN: // top = auto indent top // height = content height topValue = autoIndentTop; heightValue = 0; heightIsAuto = WEBC_TRUE; marginTopValue = GetPixelLength(CSS_PROPERTY_MARGIN_TOP, parentWidth, emHeight, exHeight, 0); break; case HEIGHT_KNOWN: // top = auto indent top // height = height topValue = autoIndentTop; heightValue = CSS_LengthToPixels(&height, parentHeight, emHeight, exHeight); heightIsAuto = WEBC_FALSE; marginTopValue = GetPixelLength(CSS_PROPERTY_MARGIN_TOP, parentWidth, emHeight, exHeight, 0); break; case TOP_KNOWN: // top = top // height = content height if (top.type == CSS_LENGTH_UNIT_PERCENT && parentHeightIsAuto) { topValue = autoIndentTop; } else { topValue = CSS_LengthToPixels(&top, parentHeight, emHeight, exHeight); } heightValue = 0; heightIsAuto = WEBC_TRUE; marginTopValue = GetPixelLength(CSS_PROPERTY_MARGIN_TOP, parentWidth, emHeight, exHeight, 0); break; case HEIGHT_KNOWN|TOP_KNOWN: // top = top // height = height if (top.type == CSS_LENGTH_UNIT_PERCENT && parentHeightIsAuto) { topValue = autoIndentTop; } else { topValue = CSS_LengthToPixels(&top, parentHeight, emHeight, exHeight); } heightValue = CSS_LengthToPixels(&height, parentHeight, emHeight, exHeight); heightIsAuto = WEBC_FALSE; marginTopValue = GetPixelLength(CSS_PROPERTY_MARGIN_TOP, parentWidth, emHeight, exHeight, 0); break; case BOTTOM_KNOWN: // bottom = bottom // height = content height // top = parentHeight - (height + bottom) bottomValue = GetPixelLength(&bottom, parentHeight, emHeight, exHeight, 0); marginBottomValue = GetPixelLength(CSS_PROPERTY_MARGIN_BOTTOM, parentWidth, emHeight, exHeight, 0); heightValue = 0; heightIsAuto = WEBC_TRUE; break; case HEIGHT_KNOWN|BOTTOM_KNOWN: // bottom = bottom // height = height // top = parentHeight - (height + bottom) bottomValue = GetPixelLength(&bottom, parentHeight, emHeight, exHeight, 0); heightValue = CSS_LengthToPixels(&height, parentHeight, emHeight, exHeight); heightIsAuto = WEBC_FALSE; marginBottomValue = GetPixelLength(CSS_PROPERTY_MARGIN_BOTTOM, parentWidth, emHeight, exHeight, 0); topValue = parentHeight - (borderTopValue + paddingTopValue + heightValue + paddingBottomValue + borderBottomValue + marginBottomValue + bottomValue); break; case TOP_KNOWN|BOTTOM_KNOWN: // top = top // bottom = bottom // height = parentHeight - (top + bottom) if (top.type == CSS_LENGTH_UNIT_PERCENT && parentHeightIsAuto) { topValue = autoIndentTop; } else { topValue = CSS_LengthToPixels(&top, parentHeight, emHeight, exHeight); } bottomValue = GetPixelLength(&bottom, parentHeight, emHeight, exHeight, 0); marginTopValue = GetPixelLength(CSS_PROPERTY_MARGIN_TOP, parentWidth, emHeight, exHeight, 0); marginBottomValue = GetPixelLength(CSS_PROPERTY_MARGIN_BOTTOM, parentWidth, emHeight, exHeight, 0); heightValue = parentHeight - (topValue + marginTopValue + borderTopValue + paddingTopValue + paddingBottomValue + borderBottomValue + marginBottomValue + bottomValue); heightIsAuto = WEBC_FALSE; break; } if (width.type != CSS_LENGTH_UNIT_AUTO) { widthValue = CSS_LengthToPixels(&width, parentWidth, emHeight, exHeight); WEBC_BOOL leftAligned = (textDirection == TU_DIR_RTL)? (right.type == CSS_LENGTH_UNIT_AUTO && left.type != CSS_LENGTH_UNIT_AUTO) : (left.type != CSS_LENGTH_UNIT_AUTO || right.type == CSS_LENGTH_UNIT_AUTO); if (leftAligned) { // ignore right and margin-right leftValue = GetPixelLength(&left, parentWidth, emHeight, exHeight, autoIndentLeft); marginLeftValue = GetPixelLength(CSS_PROPERTY_MARGIN_LEFT, parentWidth, emHeight, exHeight, 0); } else { DISPLAY_INT marginRightValue; // ignore left and margin-left rightValue = GetPixelLength(&right, parentWidth, emHeight, exHeight, autoIndentRight); marginRightValue = GetPixelLength(CSS_PROPERTY_MARGIN_RIGHT, parentWidth, emHeight, exHeight, 0); leftValue = parentWidth - (rightValue + marginRightValue + borderRightValue + paddingRightValue + widthValue + paddingLeftValue + borderLeftValue); marginLeftValue = 0; } } else { // width.type == CSS_LENGTH_UNIT_AUTO // try to get the intrinsic width of the element. This might rely on the // calculated height of the element; for example, in the case of an image with // specified height and auto width, the aspect ratio of the source image determines // the resulting intrinsic width. DISPLAY_INT marginRightValue; WEBC_BOOL hasIntrinsicWidth = GetIntrinsicWidth(&widthValue, heightValue, heightIsAuto); if (left.type == CSS_LENGTH_UNIT_AUTO && right.type != CSS_LENGTH_UNIT_AUTO && hasIntrinsicWidth) { rightValue = GetPixelLength(&right, parentWidth, emHeight, exHeight, autoIndentRight); marginRightValue = GetPixelLength(CSS_PROPERTY_MARGIN_RIGHT, parentWidth, emHeight, exHeight, 0); marginLeftValue = 0; leftValue = parentWidth - (widthValue + borderLeftValue + paddingLeftValue + paddingRightValue + borderRightValue + marginRightValue + rightValue); } else { leftValue = GetPixelLength(&left, parentWidth, emHeight, exHeight, autoIndentLeft); marginLeftValue = GetPixelLength(CSS_PROPERTY_MARGIN_LEFT, parentWidth, emHeight, exHeight, 0); if (!hasIntrinsicWidth || (right.type != CSS_LENGTH_UNIT_AUTO && left.type != CSS_LENGTH_UNIT_AUTO)) { // right and left are both non-auto, OR element has no intrinsic width: // calculate left, right, and margins then extrapolate width rightValue = GetPixelLength(&right, parentWidth, emHeight, exHeight, autoIndentRight); marginRightValue = GetPixelLength(CSS_PROPERTY_MARGIN_RIGHT, parentWidth, emHeight, exHeight, 0); widthValue = parentWidth - (leftValue + marginLeftValue + borderLeftValue + paddingLeftValue + paddingRightValue + borderRightValue + marginRightValue + rightValue); // we don't want to stretch the width beyond what the maximum content // width; only give the element as much space as it actually needs. if (right.type == CSS_LENGTH_UNIT_AUTO || left.type == CSS_LENGTH_UNIT_AUTO) { // to speed this up, bail out of GetMaxWidth when we exceed widthValue DISPLAY_INT maxWidth = GetMaxWidthSmallerThan(widthValue); // NOTE: GetMaxWidth and GetMaxWidthSmallerThan return the total width // of the element, including borders and padding. So we must subtract // borders and padding to make it correspond to the contentWidth maxWidth -= (borderLeftValue + paddingLeftValue + paddingRightValue + borderRightValue); if (maxWidth < widthValue) { WEBC_BOOL leftAligned = (textDirection == TU_DIR_RTL)? (right.type == CSS_LENGTH_UNIT_AUTO && left.type != CSS_LENGTH_UNIT_AUTO) : (left.type != CSS_LENGTH_UNIT_AUTO || right.type == CSS_LENGTH_UNIT_AUTO); if (!leftAligned) { // box is right-aligned // adjust leftValue to account for the unused space leftValue += (widthValue - maxWidth); } widthValue = maxWidth; } } } } } // Now format the content of this element DISPLAY_INT contentHeight = FormatContentPositioned ( widthValue, heightValue, heightIsAuto, borderLeftValue, borderTopValue, borderRightValue, borderBottomValue, paddingLeftValue, paddingTopValue, paddingRightValue, paddingBottomValue ); // Find the top edge and height // NOTE: top and bottom percentages are relative to parent's HEIGHT, whereas // margin-top and margin-bottom are relative to parent's WIDTH, except in the root // context (tbd - handle this special case correctly) switch (verticalCase) { case NOTHING_KNOWN: case TOP_KNOWN: heightValue = contentHeight; break; case BOTTOM_KNOWN: // height = content height // top = parentHeight - (height + bottom) heightValue = contentHeight; topValue = parentHeight - (borderTopValue + paddingTopValue + heightValue + paddingBottomValue + borderBottomValue + marginBottomValue + bottomValue); break; } rect.Set (0, 0, borderLeftValue + paddingLeftValue + widthValue + paddingRightValue + borderRightValue - 1, borderTopValue + paddingTopValue + heightValue + paddingBottomValue + borderBottomValue - 1 ); rect.MoveTo ( parentBorderLeft + leftValue + marginLeftValue, parentBorderTop + topValue + marginTopValue ); if (position == TU_POSITION_FIXED) { rect.Shift(containingBlock.left, containingBlock.top); } Move(&rect); if (generateChildContext) { childContext = childContextFactory->newPositioned ( &rect, heightIsAuto, TU_DIR_LTR, borderLeftValue, borderTopValue, borderRightValue, borderBottomValue, paddingLeftValue, paddingTopValue, paddingRightValue ); } } return (childContext); }
void WebEditBox::Format (void) { WebGraphics *gc = GetGraphics(); WebFont font = mFont.GetFont(); if (!gc || !mpText || !font) { return; } int i = 0; do { long iIndex = 0; long iNextWord; DISPLAY_INT iWidthUsed = 0; WebRect box; DISPLAY_INT iWordWidth; GetTextRect(&box); DISPLAY_INT iWidthAvailable = box.Width(); //printf("Box w == %d\n",iWidthAvailable); miMaxLineWidth = 0; miNumLines = 1; while (mpText[iIndex]) { switch (mpText[iIndex]) { case (WebChar) '\r': case (WebChar) '\n': // break the line at CR/LF AddLine(++iIndex); iWidthUsed = 0; break; default: if (!(mEditFlags & EDIT_FLAG_WRAP)) { iWordWidth = gc->TextWidthLen(&mpText[iIndex], font, 1); iWidthUsed += iWordWidth; miMaxLineWidth = EBSMAX(miMaxLineWidth, iWidthUsed); iIndex++; } else { #if (TEXT_BOX_SCROLL_DISABLED) WebChar mpText1='m'; DISPLAY_INT charWidth = gc->TextWidthLen(&mpText[iIndex], font, 1); if (iWidthUsed + charWidth > (iWidthAvailable) && iWidthUsed > 0) { AddLine(iIndex); iWidthUsed = charWidth; miMaxLineWidth = EBSMAX(miMaxLineWidth, charWidth); iIndex++; } else { iIndex++; iWidthUsed += charWidth; } }//switch statement #else if (IS_WHITESPACE(mpText[iIndex])) { iWidthUsed += gc->TextWidthLen(&mpText[iIndex++], font, 1); } else { iNextWord = iIndex; while (!IS_WHITESPACE(mpText[iNextWord]) && mpText[iNextWord]) { iNextWord++; } iWordWidth = gc->TextWidthLen(&mpText[iIndex], font, iNextWord-iIndex); // only do a line break if there is something already on the line if (iWidthUsed + iWordWidth > iWidthAvailable && iWidthUsed > 0) { // the next word_ will not fit; break the line. AddLine(iIndex); iWidthUsed = iWordWidth; miMaxLineWidth = EBSMAX(miMaxLineWidth, iWordWidth); iIndex = iNextWord; } else { // the next word_ will fit on this line iWidthUsed += iWordWidth; miMaxLineWidth = EBSMAX(miMaxLineWidth, iWordWidth); iIndex = iNextWord; } } } #endif break; } } i++; }
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 }
// x,y are in same coordinate space as this->mRect; viewX, viewY is the upper left corner of the viewport in // the coordinate space of this->mRect DisplayElement *DisplayElement::TrapEventPoint (DISPLAY_INT x, DISPLAY_INT y, DISPLAY_INT viewX, DISPLAY_INT viewY) { // if we clip our children to our rect, and the point is outside our rect, // then fail right away if (GetOverflow() == DISPLAY_OVERFLOW_HIDDEN) { WebRect clipRect; GetClipRect(&clipRect); if (!clipRect.Contains(x,y)) { return (0); } } DisplayElement *pChild = mpLastChild, *pFound; // now search positive-z children in reverse order while (pChild && (pChild->GetZIndex() >= 0)) { if (pChild->mFlags & DISPLAY_FLAG_FIXED_POS) { pFound = pChild->TrapEventPoint(x - (mRect.left + viewX), y - (mRect.top + viewY), -mRect.left, -mRect.top); } else { pFound = pChild->TrapEventPoint(x - mRect.left, y - mRect.top, viewX - mRect.left, viewY - mRect.top); } if (pFound) { return (pFound); } pChild = pChild->mpPrev; } // if we contain the point, trap it if (TrapEventInThis(x,y)) { return (this); } // now search negative-z children in reverse order while (pChild) { if (pChild->mFlags & DISPLAY_FLAG_FIXED_POS) { pFound = pChild->TrapEventPoint(x - (mRect.left + viewX), y - (mRect.top + viewY), -mRect.left, -mRect.top); } else { pFound = pChild->TrapEventPoint(x - mRect.left, y - mRect.top, viewX - mRect.left, viewY - mRect.top); } if (pFound) { return (pFound); } pChild = pChild->mpPrev; } return (0); }
void DisplayElement::Draw (DISPLAY_INT iScreenX, DISPLAY_INT iScreenY, WebRect *pViewport, WebGraphics *pGC) { DisplayElement *pChild = mpFirstChild; WebRect clip, saveClip, screenClip; WEBC_BOOL clipRestore = WEBC_FALSE; pGC->GetClip(&saveClip); clip.Set(&saveClip); if (GetOverflow() != DISPLAY_OVERFLOW_VISIBLE) //if (GetOverflow() == DISPLAY_OVERFLOW_HIDDEN) { GetClipRect(&screenClip); screenClip.Shift(iScreenX - mRect.left, iScreenY - mRect.top); if (!clip.Overlaps(&screenClip)) { // we're not visible, so neither are our children return; } clip.And(&screenClip); pGC->SetClip(&clip); clipRestore = WEBC_TRUE; } WebRect screenRect(mRect); screenRect.MoveTo(iScreenX, iScreenY); mScreenRect = screenRect; // April2013 - save the screenrect of last known draw and subtract boundaries of the display manager screenrect DisplayManager*pManager= this->GetManager(); if (pManager && pManager->mBrowser) pManager=pManager->mBrowser->GetDisplayManager(); if (pManager) { WebRect r; // printf("Not working all the way \n"); r=pManager->mScreenRect; mScreenRect.top -= r.top; mScreenRect.bottom -= r.top; mScreenRect.left -= r.left; mScreenRect.right -= r.left; } // April2013 - end save the screenrect of last known draw and subtract boundaries of the display manager screenrect // Start drawing // pGC->StartBuffer(); // Draw negative-z children while (pChild && (pChild->GetZIndex() < 0)) { if (pChild->mFlags & DISPLAY_FLAG_FIXED_POS) { pChild->Draw(pViewport->left + pChild->mRect.left, pViewport->top + pChild->mRect.top, pViewport, pGC); } else { pChild->Draw(iScreenX + pChild->mRect.left, iScreenY + pChild->mRect.top, pViewport, pGC); } pChild = pChild->mpNext; } // if I am visible if (screenRect.Overlaps(&clip)) { // Draw myself DrawThisOnly(iScreenX, iScreenY, pGC); } #if (INCLUDE_EXPERIMENTAL_DIV_SCROLLBARS) int xContentOffset=0; int yContentOffset=0; if (clipRestore && vScrollWidth() || hScrollWidth()) { WebRect contentClip; contentClip.Set(&clip); contentClip.SetHeight(contentClip.Height()-hScrollWidth()); contentClip.SetWidth(contentClip.Width()-vScrollWidth()); pGC->SetClip(&contentClip); if (GetHScroll()) { WebHScroll *pScroll = (WebHScroll *)GetHScroll(); xContentOffset=pScroll->GetPosition(); } if (GetVScroll()) { WebVScroll *pScroll = (WebVScroll *)GetVScroll(); yContentOffset=pScroll->GetPosition(); if (yContentOffset) { // If we have a y offset step i nto the content holder element // so we don't exclude the whole thing becuase it is out of our // range. // if (GetInlineContentHolder()) // pChild = GetInlineContentHolder()->mpFirstChild; ; } } } #endif // Draw positive-z children while (pChild) { #if (INCLUDE_EXPERIMENTAL_DIV_SCROLLBARS) if (pChild->IncludeInFlow() && pChild->mRect.bottom >= yContentOffset && pChild->mRect.right >= xContentOffset) { if (pChild->mFlags & DISPLAY_FLAG_FIXED_POS) { pChild->Draw(pViewport->left+pChild->mRect.left-xContentOffset, pViewport->top+pChild->mRect.top-yContentOffset, pViewport, pGC); } else { pChild->Draw(iScreenX + pChild->mRect.left-xContentOffset, iScreenY+pChild->mRect.top-yContentOffset, pViewport, pGC); } } #else if (pChild->mFlags & DISPLAY_FLAG_FIXED_POS) { pChild->Draw(pViewport->left + pChild->mRect.left, pViewport->top + pChild->mRect.top, pViewport, pGC); } else { pChild->Draw(iScreenX + pChild->mRect.left, iScreenY + pChild->mRect.top, pViewport, pGC); } #endif pChild = pChild->mpNext; } if (clipRestore) { pGC->SetClip(&saveClip); } #if (INCLUDE_EXPERIMENTAL_DIV_SCROLLBARS) if (clipRestore && vScrollWidth() || hScrollWidth()) { DisplayElement *pScroll; if (GetHScroll()) { pScroll = (WebHScroll *)GetHScroll(); pScroll->Draw(iScreenX + pScroll->mRect.left, iScreenY + pScroll->mRect.top, pViewport, pGC); } if (GetVScroll()) { pScroll = (WebVScroll *)GetVScroll(); pScroll->Draw(iScreenX + pScroll->mRect.left, iScreenY + pScroll->mRect.top, pViewport, pGC); } pGC->SetClip(&saveClip); } #endif // pGC->EndBuffer(); }
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::SetViewport (WebRect *pViewRect) { if (!mViewRect.Equals(pViewRect)) { PresetWebRect oldRect(&mViewRect); mViewportChanged = WEBC_TRUE; mViewRect.Set(pViewRect); CorrectViewportPosition(); #ifdef WEBC_BUFFER_SCROLLING if (mManagerFlags & MANAGER_FLAG_BUFFER_SCROLL) { WebGraphics* gc = this->GetGraphics(); if (gc) { if (mScrollBuffer == 0) { mScrollBuffer = gc->CreateBuffer(mViewRect.Width() * 2, mViewRect.Height() * 2); } else { if (oldRect.Width() != mViewRect.Width() || oldRect.Height() != mViewRect.Height()) { mScrollBuffer = gc->ResizeBuffer(mScrollBuffer, mViewRect.Width() * 2, mViewRect.Height() * 2); AddDirtyRect(&mViewRect); SetManagerFlag(MANAGER_FLAG_DIRTY); return; } } if (mScrollBuffer) { // find non-overlapping regions if (mViewRect.Overlaps(&oldRect)) { PresetWebRect viewRect(&mViewRect); WebRect extraRect; int count = viewRect.Split(&oldRect, &extraRect); if (count > 0) { if (count > 1) { if (count > 2) { if (!extraRect.Empty()) { AddDirtyRect(&extraRect); } } if (!oldRect.Empty()) { AddDirtyRect(&oldRect); } } if (!viewRect.Empty()) { AddDirtyRect(&viewRect); } } } else { AddDirtyRect(&mViewRect); } SetManagerFlag(MANAGER_FLAG_DIRTY); } } } #endif } }
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); }
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); } }