void RenderDialog::layout() { LayoutRepainter repainter(*this, true); LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode()); RenderBlock::layout(); RenderStyle* styleToUse = style(); if (styleToUse->position() != AbsolutePosition || !styleToUse->top().isAuto() || !styleToUse->bottom().isAuto()) { statePusher.pop(); return; } // Adjust the dialog's position to be centered in or at the top of the viewport. // FIXME: Figure out what to do in vertical writing mode. FrameView* frameView = document()->view(); int scrollTop = frameView->scrollOffset().height(); FloatPoint absolutePoint(0, scrollTop); int visibleHeight = frameView->visibleContentRect(true).height(); if (height() < visibleHeight) absolutePoint.move(0, (visibleHeight - height()) / 2); FloatPoint localPoint = containingBlock()->absoluteToLocal(absolutePoint); LayoutUnit localTop = LayoutSize(localPoint.x(), localPoint.y()).height(); setY(localTop); statePusher.pop(); // FIXME: Since there is always a layer here, repainter shouldn't be necessary. But without it, the dialog is sometimes not painted (see bug 90670). repainter.repaintAfterLayout(); }
PositionWithAffinity LayoutSVGInlineText::positionForPoint(const LayoutPoint& point) { if (!firstTextBox() || !textLength()) return createPositionWithAffinity(0, DOWNSTREAM); ASSERT(m_scalingFactor); float baseline = m_scaledFont.fontMetrics().floatAscent() / m_scalingFactor; LayoutBlock* containingBlock = this->containingBlock(); ASSERT(containingBlock); // Map local point to absolute point, as the character origins stored in the text fragments use absolute coordinates. FloatPoint absolutePoint(point); absolutePoint.moveBy(containingBlock->location()); float closestDistance = std::numeric_limits<float>::max(); float closestDistancePosition = 0; const SVGTextFragment* closestDistanceFragment = 0; SVGInlineTextBox* closestDistanceBox = 0; AffineTransform fragmentTransform; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { if (!box->isSVGInlineTextBox()) continue; SVGInlineTextBox* textBox = toSVGInlineTextBox(box); Vector<SVGTextFragment>& fragments = textBox->textFragments(); unsigned textFragmentsSize = fragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { const SVGTextFragment& fragment = fragments.at(i); FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height); fragment.buildFragmentTransform(fragmentTransform); if (!fragmentTransform.isIdentity()) fragmentRect = fragmentTransform.mapRect(fragmentRect); float distance = 0; if (!fragmentRect.contains(absolutePoint)) distance = squaredDistanceToClosestPoint(fragmentRect, absolutePoint); if (distance <= closestDistance) { closestDistance = distance; closestDistanceBox = textBox; closestDistanceFragment = &fragment; closestDistancePosition = fragmentRect.x(); } } } if (!closestDistanceFragment) return createPositionWithAffinity(0, DOWNSTREAM); int offset = closestDistanceBox->offsetForPositionInFragment(*closestDistanceFragment, absolutePoint.x() - closestDistancePosition, true); return createPositionWithAffinity(offset + closestDistanceBox->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM); }
VisiblePosition RenderSVGInlineText::positionForPoint(const LayoutPoint& point, const RenderRegion*) { if (!firstTextBox() || !textLength()) return createVisiblePosition(0, DOWNSTREAM); float baseline = m_scaledFont.fontMetrics().floatAscent(); RenderBlock* containingBlock = this->containingBlock(); ASSERT(containingBlock); // Map local point to absolute point, as the character origins stored in the text fragments use absolute coordinates. FloatPoint absolutePoint(point); absolutePoint.moveBy(containingBlock->location()); float closestDistance = std::numeric_limits<float>::max(); float closestDistancePosition = 0; const SVGTextFragment* closestDistanceFragment = nullptr; SVGInlineTextBox* closestDistanceBox = nullptr; AffineTransform fragmentTransform; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { if (!is<SVGInlineTextBox>(*box)) continue; auto& textBox = downcast<SVGInlineTextBox>(*box); Vector<SVGTextFragment>& fragments = textBox.textFragments(); unsigned textFragmentsSize = fragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { const SVGTextFragment& fragment = fragments.at(i); FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height); fragment.buildFragmentTransform(fragmentTransform); if (!fragmentTransform.isIdentity()) fragmentRect = fragmentTransform.mapRect(fragmentRect); float distance = powf(fragmentRect.x() - absolutePoint.x(), 2) + powf(fragmentRect.y() + fragmentRect.height() / 2 - absolutePoint.y(), 2); if (distance < closestDistance) { closestDistance = distance; closestDistanceBox = &textBox; closestDistanceFragment = &fragment; closestDistancePosition = fragmentRect.x(); } } } if (!closestDistanceFragment) return createVisiblePosition(0, DOWNSTREAM); int offset = closestDistanceBox->offsetForPositionInFragment(*closestDistanceFragment, absolutePoint.x() - closestDistancePosition, true); return createVisiblePosition(offset + closestDistanceBox->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM); }
VisiblePosition RenderSVGInlineText::positionForPoint(const IntPoint& point) { if (!firstTextBox() || !textLength()) return createVisiblePosition(0, DOWNSTREAM); RenderStyle* style = this->style(); ASSERT(style); int baseline = style->font().ascent(); RenderBlock* containingBlock = this->containingBlock(); ASSERT(containingBlock); // Map local point to absolute point, as the character origins stored in the text fragments use absolute coordinates. FloatPoint absolutePoint(point); absolutePoint.move(containingBlock->x(), containingBlock->y()); float closestDistance = std::numeric_limits<float>::max(); float closestDistancePosition = 0; const SVGTextFragment* closestDistanceFragment = 0; SVGInlineTextBox* closestDistanceBox = 0; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { ASSERT(box->isSVGInlineTextBox()); SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(box); Vector<SVGTextFragment>& fragments = textBox->textFragments(); unsigned textFragmentsSize = fragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { const SVGTextFragment& fragment = fragments.at(i); FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height); if (!fragment.transform.isIdentity()) fragmentRect = fragment.transform.mapRect(fragmentRect); float distance = powf(fragmentRect.x() - absolutePoint.x(), 2) + powf(fragmentRect.y() + fragmentRect.height() / 2 - absolutePoint.y(), 2); if (distance < closestDistance) { closestDistance = distance; closestDistanceBox = textBox; closestDistanceFragment = &fragment; closestDistancePosition = fragmentRect.x(); } } } if (!closestDistanceFragment) return createVisiblePosition(0, DOWNSTREAM); int offset = closestDistanceBox->offsetForPositionInFragment(*closestDistanceFragment, absolutePoint.x() - closestDistancePosition, true); return createVisiblePosition(offset + closestDistanceBox->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM); }
PositionWithAffinity LayoutSVGInlineText::positionForPoint(const LayoutPoint& point) { if (!hasTextBoxes() || !textLength()) return createPositionWithAffinity(0); ASSERT(m_scalingFactor); float baseline = m_scaledFont.getFontMetrics().floatAscent() / m_scalingFactor; LayoutBlock* containingBlock = this->containingBlock(); ASSERT(containingBlock); // Map local point to absolute point, as the character origins stored in the text fragments use absolute coordinates. FloatPoint absolutePoint(point); absolutePoint.moveBy(containingBlock->location()); float closestDistance = std::numeric_limits<float>::max(); float closestDistancePosition = 0; const SVGTextFragment* closestDistanceFragment = nullptr; SVGInlineTextBox* closestDistanceBox = nullptr; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { if (!box->isSVGInlineTextBox()) continue; SVGInlineTextBox* textBox = toSVGInlineTextBox(box); for (const SVGTextFragment& fragment : textBox->textFragments()) { FloatRect fragmentRect = fragment.boundingBox(baseline); float distance = 0; if (!fragmentRect.contains(absolutePoint)) distance = fragmentRect.squaredDistanceTo(absolutePoint); if (distance <= closestDistance) { closestDistance = distance; closestDistanceBox = textBox; closestDistanceFragment = &fragment; closestDistancePosition = fragmentRect.x(); } } } if (!closestDistanceFragment) return createPositionWithAffinity(0); int offset = closestDistanceBox->offsetForPositionInFragment(*closestDistanceFragment, LayoutUnit(absolutePoint.x() - closestDistancePosition), true); return createPositionWithAffinity(offset + closestDistanceBox->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : TextAffinity::Downstream); }
void CurveBranch::draw(const DrawContext& drawContext) { const int ANTIALIASING_STEP = 3; const bool PLAIN_DRAWING = qAbs(drawContext.thickness - 1.) < EPS; const QPair<qreal, qreal> range = findRange(drawContext.viewPort); const qreal t0 = range.first; const qreal t1 = range.second; CurveDrawer& drawer = drawContext.drawer; drawer.setAntiAliasing(drawContext.antiAliasing); QPointF absolutePoint(Curve::calcX(t0), Curve::calcY(t0)); QPointF prevPoint = drawer.toRelative(absolutePoint); drawer.fillCircle(prevPoint, drawContext.thickness); for (qreal t = t0, h; t < t1; t += h) { h = findStep(t, t1, 1 / drawContext.scale); absolutePoint = QPointF(Curve::calcX(t), Curve::calcY(t)); QPointF curPoint = drawer.toRelative(absolutePoint); QPoint drawerPoint = Utils::roundPoint(curPoint); if (PLAIN_DRAWING) { drawer.setPixel(drawerPoint); } else if (drawer.contains(drawerPoint) && (curPoint - prevPoint).manhattanLength() > ANTIALIASING_STEP) { drawer.drawLine(prevPoint, curPoint, drawContext.thickness / 2); drawer.fillCircle(curPoint, drawContext.thickness); prevPoint = curPoint; } } if (PLAIN_DRAWING == false) { QPointF lastPoint = drawer.toRelative(QPointF(Curve::calcX(t1), Curve::calcY(t1))); drawer.drawLine(prevPoint, lastPoint, drawContext.thickness / 2); drawer.fillCircle(lastPoint, drawContext.thickness); } }
bool RenderPath::nodeAtPoint(const HitTestRequest&, HitTestResult& result, int _x, int _y, int, int, HitTestAction hitTestAction) { // We only draw in the forground phase, so we only hit-test then. if (hitTestAction != HitTestForeground) return false; IntPoint absolutePoint(_x, _y); PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_PATH_HITTESTING, style()->pointerEvents()); bool isVisible = (style()->visibility() == VISIBLE); if (isVisible || !hitRules.requireVisible) { FloatPoint hitPoint = mapAbsolutePointToLocal(absolutePoint); if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke) && strokeContains(hitPoint, hitRules.requireStroke)) || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill) && fillContains(hitPoint, hitRules.requireFill))) { updateHitTestResult(result, absolutePoint); return true; } } return false; }
void gWaveform::openEditMenu() { if (selectionA == selectionB) return; menuOpen = true; Fl_Menu_Item menu[] = { {"Cut"}, {"Trim"}, {"Silence"}, {"Fade in"}, {"Fade out"}, {"Smooth edges"}, {"Set start/end here"}, {0} }; if (chan->status == STATUS_PLAY) { menu[0].deactivate(); menu[1].deactivate(); } Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50); b->box(G_BOX); b->textsize(11); b->textcolor(COLOR_TEXT_0); b->color(COLOR_BG_0); const Fl_Menu_Item *m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b); if (!m) { menuOpen = false; return; } /* straightSel() to ensure that point A is always lower than B */ straightSel(); if (strcmp(m->label(), "Silence") == 0) { wfx_silence(chan->wave, absolutePoint(selectionA), absolutePoint(selectionB)); selectionA = 0; selectionB = 0; stretchToWindow(); redraw(); menuOpen = false; return; } if (strcmp(m->label(), "Set start/end here") == 0) { glue_setBeginEndChannel( (gdEditor *) window(), // parent chan, absolutePoint(selectionA) * 2, // stereo! absolutePoint(selectionB) * 2, // stereo! false, // no recalc (we do it here) false // don't check ); selectionA = 0; selectionB = 0; selectionA_abs = 0; selectionB_abs = 0; recalcPoints(); redraw(); menuOpen = false; return; } if (strcmp(m->label(), "Cut") == 0) { wfx_cut(chan->wave, absolutePoint(selectionA), absolutePoint(selectionB)); /* for convenience reset start/end points */ glue_setBeginEndChannel( (gdEditor *) window(), chan, 0, chan->wave->size, false); selectionA = 0; selectionB = 0; selectionA_abs = 0; selectionB_abs = 0; setZoom(0); menuOpen = false; return; } if (strcmp(m->label(), "Trim") == 0) { wfx_trim(chan->wave, absolutePoint(selectionA), absolutePoint(selectionB)); glue_setBeginEndChannel( (gdEditor *) window(), chan, 0, chan->wave->size, false); selectionA = 0; selectionB = 0; selectionA_abs = 0; selectionB_abs = 0; stretchToWindow(); menuOpen = false; redraw(); return; } if (!strcmp(m->label(), "Fade in") || !strcmp(m->label(), "Fade out")) { int type = !strcmp(m->label(), "Fade in") ? 0 : 1; wfx_fade(chan->wave, absolutePoint(selectionA), absolutePoint(selectionB), type); selectionA = 0; selectionB = 0; stretchToWindow(); redraw(); menuOpen = false; return; } if (!strcmp(m->label(), "Smooth edges")) { wfx_smooth(chan->wave, absolutePoint(selectionA), absolutePoint(selectionB)); selectionA = 0; selectionB = 0; stretchToWindow(); redraw(); menuOpen = false; return; } }
int gWaveform::handle(int e) { int ret = 0; switch (e) { case FL_PUSH: { mouseX = Fl::event_x(); pushed = true; if (!mouseOnEnd() && !mouseOnStart()) { /* right button? show the menu. Don't set selectionA,B,etc */ if (Fl::event_button3()) { openEditMenu(); } else if (mouseOnSelectionA() || mouseOnSelectionB()) { resized = true; } else { dragged = true; selectionA = Fl::event_x() - x(); if (selectionA >= data.size) selectionA = data.size; selectionB = selectionA; selectionA_abs = absolutePoint(selectionA); selectionB_abs = selectionA_abs; } } ret = 1; break; } case FL_RELEASE: { /* don't recompute points if something is selected */ if (selectionA != selectionB) { pushed = false; dragged = false; ret = 1; break; } ///int realChanStart = chan->beginTrue; ///int realChanEnd = chan->endTrue; int realChanStart = chan->begin; int realChanEnd = chan->end; if (chanStartLit) realChanStart = absolutePoint(chanStart)*2; else if (chanEndLit) realChanEnd = absolutePoint(chanEnd)*2; glue_setBeginEndChannel((gdEditor *) window(), chan, realChanStart, realChanEnd, false); pushed = false; dragged = false; redraw(); ret = 1; break; } case FL_ENTER: { // enables FL_DRAG ret = 1; break; } case FL_LEAVE: { if (chanStartLit || chanEndLit) { chanStartLit = false; chanEndLit = false; redraw(); } ret = 1; break; } case FL_MOVE: { mouseX = Fl::event_x(); mouseY = Fl::event_y(); if (mouseOnStart()) { chanStartLit = true; redraw(); } else if (chanStartLit) { chanStartLit = false; redraw(); } if (mouseOnEnd()) { chanEndLit = true; redraw(); } else if (chanEndLit) { chanEndLit = false; redraw(); } if (mouseOnSelectionA()) { fl_cursor(FL_CURSOR_WE, FL_WHITE, FL_BLACK); } else if (mouseOnSelectionB()) { fl_cursor(FL_CURSOR_WE, FL_WHITE, FL_BLACK); } else { fl_cursor(FL_CURSOR_DEFAULT, FL_WHITE, FL_BLACK); } ret = 1; break; } case FL_DRAG: { if (chanStartLit && pushed) { chanStart += Fl::event_x() - mouseX; if (chanStart < 0) chanStart = 0; if (chanStart >= chanEnd) chanStart = chanEnd-2; redraw(); } else if (chanEndLit && pushed) { chanEnd += Fl::event_x() - mouseX; if (chanEnd >= data.size - 2) chanEnd = data.size - 2; if (chanEnd <= chanStart) chanEnd = chanStart + 2; redraw(); } /* here the mouse is on the waveform, i.e. a selection */ else if (dragged) { selectionB = Fl::event_x() - x(); if (selectionB >= data.size) selectionB = data.size; if (selectionB <= 0) selectionB = 0; selectionB_abs = absolutePoint(selectionB); redraw(); } else if (resized) { if (mouseOnSelectionA()) { selectionA = Fl::event_x() - x(); selectionA_abs = absolutePoint(selectionA); } else { selectionB = Fl::event_x() - x(); selectionB_abs = absolutePoint(selectionB); } redraw(); } mouseX = Fl::event_x(); ret = 1; break; } } return ret; }