IntRect enclosedIntRect(const FloatRect& rect) { IntPoint location = ceiledIntPoint(rect.minXMinYCorner()); IntPoint maxPoint = flooredIntPoint(rect.maxXMaxYCorner()); IntSize size = maxPoint - location; size.clampNegativeToZero(); return IntRect(location, size); }
void ScrollView::scrollBy(int dx, int dy) { IntSize scrollOffset = m_data->m_scrollOffset; IntSize newScrollOffset = scrollOffset + IntSize(dx, dy).shrunkTo(maximumScroll()); newScrollOffset.clampNegativeToZero(); if (newScrollOffset == scrollOffset) return; updateScrollbars(newScrollOffset); }
void ScrollbarGtk::frameRectsChanged() { if (!parent() || !platformWidget()) return; IntPoint loc = getLocationInParentWindow(frameRect()); // Don't allow the allocation size to be negative IntSize sz = frameRect().size(); sz.clampNegativeToZero(); GtkAllocation allocation = { loc.x(), loc.y(), sz.width(), sz.height() }; gtk_widget_size_allocate(platformWidget(), &allocation); }
void ScrollbarGtk::frameRectsChanged() const { if (!parent() || !parent()->isScrollViewScrollbar(this)) return; IntPoint loc = parent()->convertToContainingWindow(frameRect().location()); // Don't allow the allocation size to be negative IntSize sz = frameRect().size(); sz.clampNegativeToZero(); GtkAllocation allocation = { loc.x(), loc.y(), sz.width(), sz.height() }; gtk_widget_size_allocate(platformWidget(), &allocation); }
void PlatformScrollbar::geometryChanged() const { if (!parent()) return; ASSERT(parent()->isFrameView()); FrameView* frameView = static_cast<FrameView*>(parent()); IntRect windowRect = IntRect(frameView->contentsToWindow(frameGeometry().location()), frameGeometry().size()); IntSize sz = frameGeometry().size(); sz.clampNegativeToZero(); // GtkAllocation allocation = { windowRect.x(), windowRect.y(), sz.width(), sz.height() }; // gtk_widget_size_allocate(gtkWidget(), &allocation); }
void ScrollbarGtk::frameRectsChanged() { if (!parent()) return; ASSERT(parent()->isFrameView()); FrameView* frameView = static_cast<FrameView*>(parent()); IntRect windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size()); IntSize sz = frameRect().size(); sz.clampNegativeToZero(); GtkAllocation allocation = { windowRect.x(), windowRect.y(), sz.width(), sz.height() }; gtk_widget_size_allocate(platformWidget(), &allocation); }
void CCLayerTreeHostImpl::updateMaxScrollPosition() { if (!m_scrollLayerImpl || !m_scrollLayerImpl->children().size()) return; FloatSize viewBounds = m_viewportSize; viewBounds.scale(1 / m_pageScaleDelta); IntSize maxScroll = contentSize() - expandedIntSize(viewBounds); // The viewport may be larger than the contents in some cases, such as // having a vertical scrollbar but no horizontal overflow. maxScroll.clampNegativeToZero(); m_scrollLayerImpl->setMaxScrollPosition(maxScroll); // TODO(aelias): Also update sublayers. }
static bool encodePixels(IntSize imageSize, unsigned char* inputPixels, bool premultiplied, Vector<unsigned char>* output) { imageSize.clampNegativeToZero(); Vector<unsigned char> row; png_struct* png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); png_info* info = png_create_info_struct(png); if (!png || !info || setjmp(png_jmpbuf(png))) { png_destroy_write_struct(png ? &png : 0, info ? &info : 0); return false; } // Optimize compression for speed. // The parameters are the same as what libpng uses by default for RGB and RGBA images, except: // - the zlib compression level is 3 instead of 6, to avoid the lazy Ziv-Lempel match searching; // - the delta filter is 1 ("sub") instead of 5 ("all"), to reduce the filter computations. // The zlib memory level (8) and strategy (Z_FILTERED) will be set inside libpng. // // Avoid the zlib strategies Z_HUFFMAN_ONLY or Z_RLE. // Although they are the fastest for poorly-compressible images (e.g. photographs), // they are very slow for highly-compressible images (e.g. text, drawings or business graphics). png_set_compression_level(png, 3); png_set_filter(png, PNG_FILTER_TYPE_BASE, PNG_FILTER_SUB); png_set_write_fn(png, output, writeOutput, 0); png_set_IHDR(png, info, imageSize.width(), imageSize.height(), 8, PNG_COLOR_TYPE_RGB_ALPHA, 0, 0, 0); png_write_info(png, info); unsigned char* pixels = inputPixels; row.resize(imageSize.width() * sizeof(SkPMColor)); const size_t pixelRowStride = imageSize.width() * 4; for (int y = 0; y < imageSize.height(); ++y) { if (premultiplied) { preMultipliedBGRAtoRGBA(pixels, imageSize.width(), row.data()); png_write_row(png, row.data()); } else png_write_row(png, pixels); pixels += pixelRowStride; } png_write_end(png, info); png_destroy_write_struct(&png, &info); return true; }
static bool encodePixels(IntSize imageSize, unsigned char* inputPixels, bool premultiplied, int quality, Vector<unsigned char>* output) { JPEGOutputBuffer destination; destination.output = output; Vector<JSAMPLE> row; jpeg_compress_struct cinfo; jpeg_error_mgr error; cinfo.err = jpeg_std_error(&error); error.error_exit = handleError; jmp_buf jumpBuffer; cinfo.client_data = &jumpBuffer; if (setjmp(jumpBuffer)) { jpeg_destroy_compress(&cinfo); return false; } jpeg_create_compress(&cinfo); cinfo.dest = &destination; cinfo.dest->init_destination = prepareOutput; cinfo.dest->empty_output_buffer = writeOutput; cinfo.dest->term_destination = finishOutput; imageSize.clampNegativeToZero(); cinfo.image_height = imageSize.height(); cinfo.image_width = imageSize.width(); #if defined(JCS_EXTENSIONS) if (premultiplied) { cinfo.in_color_space = SK_B32_SHIFT ? JCS_EXT_RGBX : JCS_EXT_BGRX; cinfo.input_components = 4; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); disableSubsamplingForHighQuality(&cinfo, quality); jpeg_start_compress(&cinfo, TRUE); unsigned char* pixels = inputPixels; const size_t pixelRowStride = cinfo.image_width * 4; while (cinfo.next_scanline < cinfo.image_height) { jpeg_write_scanlines(&cinfo, &pixels, 1); pixels += pixelRowStride; } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); return true; } #endif cinfo.in_color_space = JCS_RGB; cinfo.input_components = 3; void (*extractRowRGB)(const unsigned char*, unsigned int, unsigned char* output); extractRowRGB = &RGBAtoRGB; if (premultiplied) extractRowRGB = &preMultipliedBGRAtoRGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); disableSubsamplingForHighQuality(&cinfo, quality); jpeg_start_compress(&cinfo, TRUE); unsigned char* pixels = inputPixels; row.resize(cinfo.image_width * cinfo.input_components); const size_t pixelRowStride = cinfo.image_width * 4; while (cinfo.next_scanline < cinfo.image_height) { JSAMPLE* rowData = row.data(); extractRowRGB(pixels, cinfo.image_width, rowData); jpeg_write_scanlines(&cinfo, &rowData, 1); pixels += pixelRowStride; } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); return true; }
IntSize ScrollView::maximumScroll() const { IntSize delta = (IntSize(contentsWidth(), contentsHeight()) - IntSize(visibleWidth(), visibleHeight())) - scrollOffset(); delta.clampNegativeToZero(); return delta; }
void ScrollView::updateScrollbars(const IntSize& desiredOffset) { if (m_inUpdateScrollbars || prohibitsScrolling() || platformWidget()) return; // If we came in here with the view already needing a layout, then go ahead and do that // first. (This will be the common case, e.g., when the page changes due to window resizing for example). // This layout will not re-enter updateScrollbars and does not count towards our max layout pass total. if (!m_scrollbarsSuppressed) { m_inUpdateScrollbars = true; visibleContentsResized(); m_inUpdateScrollbars = false; } bool hasHorizontalScrollbar = m_horizontalScrollbar; bool hasVerticalScrollbar = m_verticalScrollbar; bool newHasHorizontalScrollbar = hasHorizontalScrollbar; bool newHasVerticalScrollbar = hasVerticalScrollbar; ScrollbarMode hScroll = m_horizontalScrollbarMode; ScrollbarMode vScroll = m_verticalScrollbarMode; if (hScroll != ScrollbarAuto) newHasHorizontalScrollbar = (hScroll == ScrollbarAlwaysOn); if (vScroll != ScrollbarAuto) newHasVerticalScrollbar = (vScroll == ScrollbarAlwaysOn); if (m_scrollbarsSuppressed || (hScroll != ScrollbarAuto && vScroll != ScrollbarAuto)) { if (hasHorizontalScrollbar != newHasHorizontalScrollbar) setHasHorizontalScrollbar(newHasHorizontalScrollbar); if (hasVerticalScrollbar != newHasVerticalScrollbar) setHasVerticalScrollbar(newHasVerticalScrollbar); } else { bool sendContentResizedNotification = false; IntSize docSize = contentsSize(); IntSize frameSize = frameRect().size(); if (hScroll == ScrollbarAuto) { newHasHorizontalScrollbar = docSize.width() > visibleWidth(); if (newHasHorizontalScrollbar && !m_updateScrollbarsPass && docSize.width() <= frameSize.width() && docSize.height() <= frameSize.height()) newHasHorizontalScrollbar = false; } if (vScroll == ScrollbarAuto) { newHasVerticalScrollbar = docSize.height() > visibleHeight(); if (newHasVerticalScrollbar && !m_updateScrollbarsPass && docSize.width() <= frameSize.width() && docSize.height() <= frameSize.height()) newHasVerticalScrollbar = false; } // If we ever turn one scrollbar off, always turn the other one off too. Never ever // try to both gain/lose a scrollbar in the same pass. if (!newHasHorizontalScrollbar && hasHorizontalScrollbar && vScroll != ScrollbarAlwaysOn) newHasVerticalScrollbar = false; if (!newHasVerticalScrollbar && hasVerticalScrollbar && hScroll != ScrollbarAlwaysOn) newHasHorizontalScrollbar = false; if (hasHorizontalScrollbar != newHasHorizontalScrollbar) { setHasHorizontalScrollbar(newHasHorizontalScrollbar); sendContentResizedNotification = true; } if (hasVerticalScrollbar != newHasVerticalScrollbar) { setHasVerticalScrollbar(newHasVerticalScrollbar); sendContentResizedNotification = true; } if (sendContentResizedNotification && m_updateScrollbarsPass < cMaxUpdateScrollbarsPass) { m_updateScrollbarsPass++; contentsResized(); visibleContentsResized(); IntSize newDocSize = contentsSize(); if (newDocSize == docSize) { // The layout with the new scroll state had no impact on // the document's overall size, so updateScrollbars didn't get called. // Recur manually. updateScrollbars(desiredOffset); } m_updateScrollbarsPass--; } } // Set up the range (and page step/line step), but only do this if we're not in a nested call (to avoid // doing it multiple times). if (m_updateScrollbarsPass) return; m_inUpdateScrollbars = true; IntSize maxScrollPosition(contentsWidth() - visibleWidth(), contentsHeight() - visibleHeight()); IntSize scroll = desiredOffset.shrunkTo(maxScrollPosition); scroll.clampNegativeToZero(); if (m_horizontalScrollbar) { int clientWidth = visibleWidth(); m_horizontalScrollbar->setEnabled(contentsWidth() > clientWidth); int pageStep = max(max<int>(clientWidth * Scrollbar::minFractionToStepWhenPaging(), clientWidth - Scrollbar::maxOverlapBetweenPages()), 1); IntRect oldRect(m_horizontalScrollbar->frameRect()); IntRect hBarRect = IntRect(0, height() - m_horizontalScrollbar->height(), width() - (m_verticalScrollbar ? m_verticalScrollbar->width() : 0), m_horizontalScrollbar->height()); m_horizontalScrollbar->setFrameRect(hBarRect); if (!m_scrollbarsSuppressed && oldRect != m_horizontalScrollbar->frameRect()) m_horizontalScrollbar->invalidate(); if (m_scrollbarsSuppressed) m_horizontalScrollbar->setSuppressInvalidation(true); m_horizontalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep); m_horizontalScrollbar->setProportion(clientWidth, contentsWidth()); m_horizontalScrollbar->setValue(scroll.width()); if (m_scrollbarsSuppressed) m_horizontalScrollbar->setSuppressInvalidation(false); } if (m_verticalScrollbar) { int clientHeight = visibleHeight(); m_verticalScrollbar->setEnabled(contentsHeight() > clientHeight); int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1); IntRect oldRect(m_verticalScrollbar->frameRect()); IntRect vBarRect = IntRect(width() - m_verticalScrollbar->width(), 0, m_verticalScrollbar->width(), height() - (m_horizontalScrollbar ? m_horizontalScrollbar->height() : 0)); m_verticalScrollbar->setFrameRect(vBarRect); if (!m_scrollbarsSuppressed && oldRect != m_verticalScrollbar->frameRect()) m_verticalScrollbar->invalidate(); if (m_scrollbarsSuppressed) m_verticalScrollbar->setSuppressInvalidation(true); m_verticalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep); m_verticalScrollbar->setProportion(clientHeight, contentsHeight()); m_verticalScrollbar->setValue(scroll.height()); if (m_scrollbarsSuppressed) m_verticalScrollbar->setSuppressInvalidation(false); } if (hasHorizontalScrollbar != (m_horizontalScrollbar != 0) || hasVerticalScrollbar != (m_verticalScrollbar != 0)) { frameRectsChanged(); updateScrollCorner(); } // See if our offset has changed in a situation where we might not have scrollbars. // This can happen when editing a body with overflow:hidden and scrolling to reveal selection. // It can also happen when maximizing a window that has scrollbars (but the new maximized result // does not). IntSize scrollDelta = scroll - m_scrollOffset; if (scrollDelta != IntSize()) { m_scrollOffset = scroll; scrollContents(scrollDelta); } m_inUpdateScrollbars = false; }
IntPoint ScrollView::maximumScrollPosition() const { IntSize maximumOffset = contentsSize() - visibleContentRect().size(); maximumOffset.clampNegativeToZero(); return IntPoint(maximumOffset.width(), maximumOffset.height()); }
void ScrollView::updateScrollbars(const IntSize& desiredOffset) { // Don't allow re-entrancy into this function. if (m_data->m_inUpdateScrollbars) return; // FIXME: This code is here so we don't have to fork FrameView.h/.cpp. // In the end, FrameView should just merge with ScrollView. if (static_cast<const FrameView*>(this)->frame()->prohibitsScrolling()) return; m_data->m_inUpdateScrollbars = true; bool hasVerticalScrollbar = m_data->m_vBar; bool hasHorizontalScrollbar = m_data->m_hBar; bool oldHasVertical = hasVerticalScrollbar; bool oldHasHorizontal = hasHorizontalScrollbar; ScrollbarMode hScroll = m_data->m_hScrollbarMode; ScrollbarMode vScroll = m_data->m_vScrollbarMode; const int cVerticalWidth = PlatformScrollbar::verticalScrollbarWidth(); const int cHorizontalHeight = PlatformScrollbar::horizontalScrollbarHeight(); for (int pass = 0; pass < 2; pass++) { bool scrollsVertically; bool scrollsHorizontally; if (!m_data->m_scrollbarsSuppressed && (hScroll == ScrollbarAuto || vScroll == ScrollbarAuto)) { // Do a layout if pending before checking if scrollbars are needed. if (hasVerticalScrollbar != oldHasVertical || hasHorizontalScrollbar != oldHasHorizontal) static_cast<FrameView*>(this)->layout(); scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() > height()); if (scrollsVertically) scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() + cVerticalWidth > width()); else { scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() > width()); if (scrollsHorizontally) scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() + cHorizontalHeight > height()); } } else { scrollsHorizontally = (hScroll == ScrollbarAuto) ? hasHorizontalScrollbar : (hScroll == ScrollbarAlwaysOn); scrollsVertically = (vScroll == ScrollbarAuto) ? hasVerticalScrollbar : (vScroll == ScrollbarAlwaysOn); } if (hasVerticalScrollbar != scrollsVertically) { m_data->setHasVerticalScrollbar(scrollsVertically); hasVerticalScrollbar = scrollsVertically; } if (hasHorizontalScrollbar != scrollsHorizontally) { m_data->setHasHorizontalScrollbar(scrollsHorizontally); hasHorizontalScrollbar = scrollsHorizontally; } } // Set up the range (and page step/line step). IntSize maxScrollPosition(contentsWidth() - visibleWidth(), contentsHeight() - visibleHeight()); IntSize scroll = desiredOffset.shrunkTo(maxScrollPosition); scroll.clampNegativeToZero(); if (m_data->m_hBar) { int clientWidth = visibleWidth(); m_data->m_hBar->setEnabled(contentsWidth() > clientWidth); int pageStep = (clientWidth - PAGE_KEEP); if (pageStep < 0) pageStep = clientWidth; IntRect oldRect(m_data->m_hBar->frameGeometry()); IntRect hBarRect = IntRect(0, height() - m_data->m_hBar->height(), width() - (m_data->m_vBar ? m_data->m_vBar->width() : 0), m_data->m_hBar->height()); m_data->m_hBar->setRect(hBarRect); if (!m_data->m_scrollbarsSuppressed && oldRect != m_data->m_hBar->frameGeometry()) m_data->m_hBar->invalidate(); if (m_data->m_scrollbarsSuppressed) m_data->m_hBar->setSuppressInvalidation(true); m_data->m_hBar->setSteps(LINE_STEP, pageStep); m_data->m_hBar->setProportion(clientWidth, contentsWidth()); m_data->m_hBar->setValue(scroll.width()); if (m_data->m_scrollbarsSuppressed) m_data->m_hBar->setSuppressInvalidation(false); } if (m_data->m_vBar) { int clientHeight = visibleHeight(); m_data->m_vBar->setEnabled(contentsHeight() > clientHeight); int pageStep = (clientHeight - PAGE_KEEP); if (pageStep < 0) pageStep = clientHeight; IntRect oldRect(m_data->m_vBar->frameGeometry()); IntRect vBarRect = IntRect(width() - m_data->m_vBar->width(), 0, m_data->m_vBar->width(), height() - (m_data->m_hBar ? m_data->m_hBar->height() : 0)); m_data->m_vBar->setRect(vBarRect); if (!m_data->m_scrollbarsSuppressed && oldRect != m_data->m_vBar->frameGeometry()) m_data->m_vBar->invalidate(); if (m_data->m_scrollbarsSuppressed) m_data->m_vBar->setSuppressInvalidation(true); m_data->m_vBar->setSteps(LINE_STEP, pageStep); m_data->m_vBar->setProportion(clientHeight, contentsHeight()); m_data->m_vBar->setValue(scroll.height()); if (m_data->m_scrollbarsSuppressed) m_data->m_vBar->setSuppressInvalidation(false); } if (oldHasVertical != (m_data->m_vBar != 0) || oldHasHorizontal != (m_data->m_hBar != 0)) geometryChanged(); // See if our offset has changed in a situation where we might not have scrollbars. // This can happen when editing a body with overflow:hidden and scrolling to reveal selection. // It can also happen when maximizing a window that has scrollbars (but the new maximized result // does not). IntSize scrollDelta = scroll - m_data->m_scrollOffset; if (scrollDelta != IntSize()) { m_data->m_scrollOffset = scroll; m_data->scrollBackingStore(scrollDelta); } m_data->m_inUpdateScrollbars = false; }