void SelectionMarkerController::updateInternal() { if(m_inController) return; m_inController = true; FrameSelection* selection = m_frame->selection(); ASSERT(selection); IntRect selectionBounds = enclosingIntRect(selection->bounds()); if(selectionBounds.isEmpty()) { hideMarkers(); m_inController = false; return; } attachMarkers(); IntPoint start(selectionBounds.x(), selectionBounds.y()); IntPoint end(selectionBounds.x() + selectionBounds.width(), selectionBounds.y() + selectionBounds.height()); IntRect bounds = offsetForPosition(selection->start()); if(!bounds.isEmpty()) { start = bounds.location(); } bounds = offsetForPosition(selection->end()); if(!bounds.isEmpty()) { end.setX(bounds.maxX()); end.setY(bounds.maxY()); } showMarkers(start, end); m_inController = false; }
VisiblePosition RenderTextLineBoxes::positionForPoint(const RenderText& renderer, const LayoutPoint& point) const { if (!m_first || !renderer.textLength()) return renderer.createVisiblePosition(0, DOWNSTREAM); LayoutUnit pointLineDirection = m_first->isHorizontal() ? point.x() : point.y(); LayoutUnit pointBlockDirection = m_first->isHorizontal() ? point.y() : point.x(); bool blocksAreFlipped = renderer.style().isFlippedBlocksWritingMode(); InlineTextBox* lastBox = nullptr; for (auto box = m_first; box; box = box->nextTextBox()) { if (box->isLineBreak() && !box->prevLeafChild() && box->nextLeafChild() && !box->nextLeafChild()->isLineBreak()) box = box->nextTextBox(); auto& rootBox = box->root(); LayoutUnit top = std::min(rootBox.selectionTop(), rootBox.lineTop()); if (pointBlockDirection > top || (!blocksAreFlipped && pointBlockDirection == top)) { LayoutUnit bottom = rootBox.selectionBottom(); if (rootBox.nextRootBox()) bottom = std::min(bottom, rootBox.nextRootBox()->lineTop()); if (pointBlockDirection < bottom || (blocksAreFlipped && pointBlockDirection == bottom)) { ShouldAffinityBeDownstream shouldAffinityBeDownstream; #if PLATFORM(IOS) if (pointLineDirection != box->logicalLeft() && point.x() < box->x() + box->logicalWidth()) { int half = box->x() + box->logicalWidth() / 2; EAffinity affinity = point.x() < half ? DOWNSTREAM : VP_UPSTREAM_IF_POSSIBLE; return renderer.createVisiblePosition(box->offsetForPosition(pointLineDirection) + box->start(), affinity); } #endif if (lineDirectionPointFitsInBox(pointLineDirection, *box, shouldAffinityBeDownstream)) return createVisiblePositionAfterAdjustingOffsetForBiDi(*box, box->offsetForPosition(pointLineDirection), shouldAffinityBeDownstream); } } lastBox = box; } if (lastBox) { ShouldAffinityBeDownstream shouldAffinityBeDownstream; lineDirectionPointFitsInBox(pointLineDirection, *lastBox, shouldAffinityBeDownstream); return createVisiblePositionAfterAdjustingOffsetForBiDi(*lastBox, lastBox->offsetForPosition(pointLineDirection) + lastBox->start(), shouldAffinityBeDownstream); } return renderer.createVisiblePosition(0, DOWNSTREAM); }
void fill(const rgb& clr) { u_int32_t *wptr = (u_int32_t*)(m_fb + offsetForPosition(0, 0, m_active_buffer)); for ( int y = 0; y < m_vinfo.yres; y ++ ) { for ( int x = 0; x < m_vinfo.xres_virtual; x ++ ) { *wptr++ = clr; } } }
void vline(int x, int y1, int y2, const rgb& clr) { u_int32_t *wptr = (u_int32_t*)( m_fb + offsetForPosition( x, y1, m_active_buffer ) ); ptrdiff_t dist = (u_int32_t*)( m_fb + offsetForPosition( x, y1+1, m_active_buffer ) ) - wptr; for (int y = y1; y < y2; y++) { *wptr = clr; wptr += dist; } }
void hline(int x1, int x2, int y, const rgb& clr) { u_int32_t *wptr = (u_int32_t*)( m_fb + offsetForPosition( x1, y, m_active_buffer ) ); for ( int x = x1; x < x2; x ++ ) { *wptr++ = clr; } }
int InlineTextBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox) { if (foundBox) { m_truncation = cFullTruncation; return -1; } int ellipsisX = ltr ? blockEdge - ellipsisWidth : blockEdge + ellipsisWidth; // For LTR, if the left edge of the ellipsis is to the left of our text run, then we are the run that will get truncated. if (ltr) { if (ellipsisX <= m_x) { // Too far. Just set full truncation, but return -1 and let the ellipsis just be placed at the edge of the box. m_truncation = cFullTruncation; foundBox = true; return -1; } if (ellipsisX < m_x + m_width) { if (direction() == RTL) return -1; // FIXME: Support LTR truncation when the last run is RTL someday. foundBox = true; int offset = offsetForPosition(ellipsisX, false); if (offset == 0) { // No characters should be rendered. Set ourselves to full truncation and place the ellipsis at the min of our start // and the ellipsis edge. m_truncation = cFullTruncation; return min(ellipsisX, m_x); } // Set the truncation index on the text run. The ellipsis needs to be placed just after the last visible character. m_truncation = offset; return m_x + static_cast<RenderText*>(m_object)->width(m_start, offset, textPos(), m_firstLine); } } else { // FIXME: Support RTL truncation someday, including both modes (when the leftmost run on the line is either RTL or LTR) } return -1; }
void fill(const Rect& area, const rgb& clr) { for ( int y = 0; y < area.getSize().getHeight(); y ++ ) { u_int32_t *wptr = (u_int32_t*)( m_fb + offsetForPosition( area.getOrigin().getX(), area.getOrigin().getY() + y, m_active_buffer ) ); for ( int x = 0; x < area.getSize().getWidth(); x ++ ) { *wptr++ = clr; } } }
void drawImage(const Point& dst, const Image* img, const Rect& srcRect, bool negative) { int width = srcRect.getSize().getWidth(); int height = srcRect.getSize().getHeight(); int len = width * img->bytesPerPixel(); u_int32_t dstStartingOffset = offsetForPosition( dst.getX(), dst.getY(), m_active_buffer ); u_int32_t dstPtrStep = offsetForPosition( dst.getX(), dst.getY() + 1, m_active_buffer ) - dstStartingOffset; dstPtrStep /= sizeof(u_int32_t); u_int32_t srcStartingOffset = img->offsetForPosition( srcRect.getOrigin().getX(), srcRect.getOrigin().getY() ); u_int32_t srcPtrStep = img->offsetForPosition( srcRect.getOrigin().getX(), srcRect.getOrigin().getY() + 1 ) - srcStartingOffset; srcPtrStep /= sizeof(u_int32_t); u_int32_t *w_ptr = (u_int32_t*) ( m_fb + dstStartingOffset ); u_int32_t *r_ptr = (u_int32_t*) ( img->buffer() + srcStartingOffset ); if ( !negative ) { for ( int y = 0; y < height; y ++ ) { memcpy(w_ptr, r_ptr, len); w_ptr += dstPtrStep; r_ptr += srcPtrStep; } } else { for ( int y = 0; y < height; y ++ ) { u_int32_t *w = w_ptr; u_int32_t *r = r_ptr; for (int x = 0; x < width; x ++ ) { *w = (~*r)&0x00ffffff; w++; r++; } w_ptr += dstPtrStep; r_ptr += srcPtrStep; } } }
LayoutUnit InlineTextBox::placeEllipsisBox(bool flowIsLTR, LayoutUnit visibleLeftEdge, LayoutUnit visibleRightEdge, LayoutUnit ellipsisWidth, LayoutUnit &truncatedWidth, bool& foundBox) { if (foundBox) { setTruncation(cFullTruncation); return -1; } // For LTR this is the left edge of the box, for RTL, the right edge in parent coordinates. LayoutUnit ellipsisX = flowIsLTR ? visibleRightEdge - ellipsisWidth : visibleLeftEdge + ellipsisWidth; // Criteria for full truncation: // LTR: the left edge of the ellipsis is to the left of our text run. // RTL: the right edge of the ellipsis is to the right of our text run. bool ltrFullTruncation = flowIsLTR && ellipsisX <= logicalLeft(); bool rtlFullTruncation = !flowIsLTR && ellipsisX >= logicalLeft() + logicalWidth(); if (ltrFullTruncation || rtlFullTruncation) { // Too far. Just set full truncation, but return -1 and let the ellipsis just be placed at the edge of the box. setTruncation(cFullTruncation); foundBox = true; return -1; } bool ltrEllipsisWithinBox = flowIsLTR && (ellipsisX < logicalRight()); bool rtlEllipsisWithinBox = !flowIsLTR && (ellipsisX > logicalLeft()); if (ltrEllipsisWithinBox || rtlEllipsisWithinBox) { foundBox = true; // The inline box may have different directionality than it's parent. Since truncation // behavior depends both on both the parent and the inline block's directionality, we // must keep track of these separately. bool ltr = isLeftToRightDirection(); if (ltr != flowIsLTR) { // Width in pixels of the visible portion of the box, excluding the ellipsis. int visibleBoxWidth = visibleRightEdge - visibleLeftEdge - ellipsisWidth; ellipsisX = ltr ? logicalLeft() + visibleBoxWidth : logicalRight() - visibleBoxWidth; } int offset = offsetForPosition(ellipsisX, false); if (offset == 0) { // No characters should be laid out. Set ourselves to full truncation and place the ellipsis at the min of our start // and the ellipsis edge. setTruncation(cFullTruncation); truncatedWidth += ellipsisWidth; return std::min(ellipsisX, logicalLeft()); } // Set the truncation index on the text run. setTruncation(offset); // If we got here that means that we were only partially truncated and we need to return the pixel offset at which // to place the ellipsis. LayoutUnit widthOfVisibleText = lineLayoutItem().width(m_start, offset, textPos(), flowIsLTR ? LTR : RTL, isFirstLineStyle()); // The ellipsis needs to be placed just after the last visible character. // Where "after" is defined by the flow directionality, not the inline // box directionality. // e.g. In the case of an LTR inline box truncated in an RTL flow then we can // have a situation such as |Hello| -> |...He| truncatedWidth += widthOfVisibleText + ellipsisWidth; if (flowIsLTR) return logicalLeft() + widthOfVisibleText; return logicalRight() - widthOfVisibleText - ellipsisWidth; } truncatedWidth += logicalWidth(); return -1; }