void Screen::flushScaleImage(ImageFrame *frame, const Common::Point &pt, int16 *xp, int16 *yp, int16 *width_, int16 *height_, int scaleVal) { Common::Point imgPos(pt.x + frame->sDrawXOffset(scaleVal), pt.y + frame->sDrawYOffset(scaleVal)); Common::Rect newBounds(imgPos.x, imgPos.y, imgPos.x + frame->sDrawXSize(scaleVal), imgPos.y + frame->sDrawYSize(scaleVal)); Common::Rect oldBounds(*xp, *yp, *xp + *width_, *yp + *height_); if (!_flushScreen) { // See if the areas of the old and new overlap, and if so combine the areas if (newBounds.intersects(oldBounds)) { Common::Rect mergedBounds = newBounds; mergedBounds.extend(oldBounds); mergedBounds.right += 1; mergedBounds.bottom += 1; slamRect(mergedBounds); } else { // The two areas are independent, so copy them both slamRect(newBounds); slamRect(oldBounds); } } *xp = newBounds.left; *yp = newBounds.top; *width_ = newBounds.width(); *height_ = newBounds.height(); }
void RenderWidget::updateWidgetPosition() { if (!m_widget) return; // FIXME: This doesn't work correctly with transforms. FloatPoint absPos = localToAbsolute(); absPos.move(borderLeft() + paddingLeft(), borderTop() + paddingTop()); int w = width() - borderLeft() - borderRight() - paddingLeft() - paddingRight(); int h = height() - borderTop() - borderBottom() - paddingTop() - paddingBottom(); IntRect newBounds(absPos.x(), absPos.y(), w, h); IntRect oldBounds(m_widget->frameRect()); if (newBounds != oldBounds) { // The widget changed positions. Update the frame geometry. if (checkForRepaintDuringLayout()) { RenderView* v = view(); if (!v->printing()) { // FIXME: do container-relative repaint v->repaintRectangleInViewAndCompositedLayers(oldBounds); v->repaintRectangleInViewAndCompositedLayers(newBounds); } } RenderArena* arena = ref(); element()->ref(); m_widget->setFrameRect(newBounds); element()->deref(); deref(arena); } }
void Screen::flushImage(ImageFrame *frame, const Common::Point &pt, int16 *xp, int16 *yp, int16 *width, int16 *height) { Common::Point imgPos = pt + frame->_offset; Common::Rect newBounds(imgPos.x, imgPos.y, imgPos.x + frame->_frame.w, imgPos.y + frame->_frame.h); Common::Rect oldBounds(*xp, *yp, *xp + *width, *yp + *height); if (!_flushScreen) { // See if the areas of the old and new overlap, and if so combine the areas if (newBounds.intersects(oldBounds)) { Common::Rect mergedBounds = newBounds; mergedBounds.extend(oldBounds); mergedBounds.right += 1; mergedBounds.bottom += 1; slamRect(mergedBounds); } else { // The two areas are independent, so copy them both slamRect(newBounds); slamRect(oldBounds); } } *xp = newBounds.left; *yp = newBounds.top; *width = newBounds.width(); *height = newBounds.height(); }
void RenderWidget::updateWidgetPosition() { if (!m_widget) return; // FIXME: This doesn't work correctly with transforms. FloatPoint absPos = localToAbsolute(); absPos.move(borderLeft() + paddingLeft(), borderTop() + paddingTop()); int w = width() - borderLeft() - borderRight() - paddingLeft() - paddingRight(); int h = height() - borderTop() - borderBottom() - paddingTop() - paddingBottom(); IntRect newBounds(absPos.x(), absPos.y(), w, h); IntRect oldBounds(m_widget->frameRect()); bool boundsChanged = newBounds != oldBounds; if (boundsChanged) { RenderArena* arena = ref(); node()->ref(); m_widget->setFrameRect(newBounds); node()->deref(); deref(arena); } // if the frame bounds got changed, or if view needs layout (possibly indicating // content size is wrong) we have to do a layout to set the right widget size if (m_widget->isFrameView()) { FrameView* frameView = static_cast<FrameView*>(m_widget.get()); if (boundsChanged || frameView->needsLayout()) frameView->layout(); } }
void RenderWidget::updateWidgetPosition() { if (!m_widget) return; int x; int y; absolutePosition(x, y); x += borderLeft() + paddingLeft(); y += borderTop() + paddingTop(); int width = m_width - borderLeft() - borderRight() - paddingLeft() - paddingRight(); int height = m_height - borderTop() - borderBottom() - paddingTop() - paddingBottom(); IntRect newBounds(x, y, width, height); IntRect oldBounds(m_widget->frameGeometry()); if (newBounds != oldBounds) { // The widget changed positions. Update the frame geometry. if (checkForRepaintDuringLayout()) { RenderView* v = view(); if (!v->printing()) { v->repaintViewRectangle(oldBounds); v->repaintViewRectangle(newBounds); } } RenderArena* arena = ref(); element()->ref(); m_widget->setFrameGeometry(newBounds); element()->deref(); deref(arena); } }
void TWindow::SetBounds(const TRect& bounds) { if (fWindow) XMoveResizeWindow(sDisplay, fWindow, bounds.left, bounds.top, bounds.GetWidth(), bounds.GetHeight()); // do the notification for child windows or unmapped windows. if ((!fWindow || fParent) && bounds != fBounds) { TRect oldBounds(fBounds); fBounds = bounds; NotifyBoundsChanged(oldBounds); } }
void SearchAgent::reset(const SteerLib::AgentInitialConditions & initialConditions, SteerLib::EngineInterface * engineInfo) { // compute the "old" bounding box of the agent before it is reset. its OK that it will be invalid if the agent was previously disabled // because the value is not used in that case. std::cout<<"Reset is called"; Util::AxisAlignedBox oldBounds(__position.x-_radius, __position.x+_radius, 0.0f, 0.0f, __position.z-_radius, __position.z+_radius); // initialize the agent based on the initial conditions __position = initialConditions.position; _forward = initialConditions.direction; _radius = initialConditions.radius; _velocity = initialConditions.speed * Util::normalize(initialConditions.direction); // compute the "new" bounding box of the agent Util::AxisAlignedBox newBounds(__position.x-_radius, __position.x+_radius, 0.0f, 0.0f, __position.z-_radius, __position.z+_radius); if (!_enabled) { // if the agent was not enabled, then it does not already exist in the database, so add it. gSpatialDatabase->addObject( this, newBounds); } else { // if the agent was enabled, then the agent already existed in the database, so update it instead of adding it. gSpatialDatabase->updateObject( this, oldBounds, newBounds); } _enabled = true; if (initialConditions.goals.size() == 0) { throw Util::GenericException("No goals were specified!\n"); } // iterate over the sequence of goals specified by the initial conditions. for (unsigned int i=0; i<initialConditions.goals.size(); i++) { if (initialConditions.goals[i].goalType == SteerLib::GOAL_TYPE_SEEK_STATIC_TARGET) { _goalQueue.push(initialConditions.goals[i]); if (initialConditions.goals[i].targetIsRandom) { // if the goal is random, we must randomly generate the goal. _goalQueue.back().targetLocation = gSpatialDatabase->randomPositionWithoutCollisions(1.0f, true); } } else { throw Util::GenericException("Unsupported goal type; SearchAgent only supports GOAL_TYPE_SEEK_STATIC_TARGET."); } } assert(_forward.length()!=0.0f); assert(_goalQueue.size() != 0); assert(_radius != 0.0f); }
void CurveAgent::_doEulerStep(const Util::Vector & steeringDecisionForce, float dt) { // compute acceleration, _velocity, and newPosition by a simple Euler step const Util::Vector clippedForce = Util::clamp(steeringDecisionForce, MAX_FORCE_MAGNITUDE); Util::Vector acceleration = (clippedForce / AGENT_MASS); _velocity = _velocity + (dt*acceleration); _velocity = clamp(_velocity, MAX_SPEED); // clamp _velocity to the max speed const Util::Point newPosition = __position + (dt*_velocity); // For this simple agent, we just make the orientation point along the agent's current velocity. if (_velocity.lengthSquared() != 0.0f) { _forward = normalize(_velocity); } // update the database with the new agent's setup Util::AxisAlignedBox oldBounds(__position.x - _radius, __position.x + _radius, 0.0f, 0.0f, __position.z - _radius, __position.z + _radius); Util::AxisAlignedBox newBounds(newPosition.x - _radius, newPosition.x + _radius, 0.0f, 0.0f, newPosition.z - _radius, newPosition.z + _radius); gSpatialDatabase->updateObject( this, oldBounds, newBounds); __position = newPosition; }
void CurveAgent::updateAI(float timeStamp, float dt, unsigned int frameNumber) { //For this function, we assume that all goals are of type GOAL_TYPE_SEEK_STATIC_TARGET. //The error check for this was performed in reset(). Util::AutomaticFunctionProfiler profileThisFunction( &CurveAIGlobals::gPhaseProfilers->aiProfiler ); Util::Point newPosition; //Move one step on hermiteCurve if (!curve.calculatePoint(newPosition, timeStamp+dt)) { disable(); return; } //Update the database with the new agent's setup Util::AxisAlignedBox oldBounds(__position.x - _radius, __position.x + _radius, 0.0f, 0.0f, __position.z - _radius, __position.z + _radius); Util::AxisAlignedBox newBounds(newPosition.x - _radius, newPosition.x + _radius, 0.0f, 0.0f, newPosition.z - _radius, newPosition.z + _radius); gSpatialDatabase->updateObject(this, oldBounds, newBounds); //Update current position __position = newPosition; }
void SearchAgent::updateAI(float timeStamp, float dt, unsigned int frameNumber) { Util::AutomaticFunctionProfiler profileThisFunction( &SearchAIGlobals::gPhaseProfilers->aiProfiler ); double steps = (DURATION/(double)__path.size()); if(timeStamp*dt > last_waypoint*steps) { if(!_goalQueue.empty()) { Util::AxisAlignedBox oldBounds(__position.x - _radius, __position.x + _radius, 0.0f, 0.0f, __position.z - _radius, __position.z + _radius); __position = _goalQueue.front().targetLocation; std::cout << "Waypoint: " << __position; _goalQueue.pop(); last_waypoint++; Util::AxisAlignedBox newBounds(__position.x - _radius, __position.x + _radius, 0.0f, 0.0f, __position.z - _radius, __position.z + _radius); gSpatialDatabase->updateObject(this, oldBounds, newBounds); } } }
void CurveAgent::reset(const SteerLib::AgentInitialConditions & initialConditions, SteerLib::EngineInterface * engineInfo) { // compute the "old" bounding box of the agent before it is reset. its OK that it will be invalid if the agent was previously disabled // because the value is not used in that case. Util::AxisAlignedBox oldBounds(__position.x-_radius, __position.x+_radius, 0.0f, 0.0f, __position.z-_radius, __position.z+_radius); // initialize the agent based on the initial conditions __startPosition = initialConditions.position; __position = initialConditions.position; _forward = initialConditions.direction; _radius = initialConditions.radius; _velocity = initialConditions.speed * Util::normalize(initialConditions.direction); // Find random agent color if (initialConditions.colorSet) agentColor = initialConditions.color; else { std::random_device seed; std::default_random_engine generator(seed()); std::uniform_real_distribution<float> distribution(0.0f, 0.8f); agentColor = Util::Color(distribution(generator), distribution(generator), distribution(generator)); } // compute the "new" bounding box of the agent Util::AxisAlignedBox newBounds(__position.x-_radius, __position.x+_radius, 0.0f, 0.0f, __position.z-_radius, __position.z+_radius); if (!_enabled) { // if the agent was not enabled, then it does not already exist in the database, so add it. gSpatialDatabase->addObject( this, newBounds); } else { // if the agent was enabled, then the agent already existed in the database, so update it instead of adding it. gSpatialDatabase->updateObject( this, oldBounds, newBounds); } _enabled = true; if (initialConditions.goals.size() == 0) { throw Util::GenericException("No goals were specified!\n"); } // iterate over the sequence of goals specified by the initial conditions. for (unsigned int i=0; i<initialConditions.goals.size(); i++) { if (initialConditions.goals[i].goalType == SteerLib::GOAL_TYPE_SEEK_STATIC_TARGET) { _goalQueue.push_back(initialConditions.goals[i]); if (initialConditions.goals[i].targetIsRandom) { // if the goal is random, we must randomly generate the goal. _goalQueue.back().targetLocation = gSpatialDatabase->randomPositionWithoutCollisions(1.0f, true); } } else { throw Util::GenericException("Unsupported goal type; CurveAgent only supports GOAL_TYPE_SEEK_STATIC_TARGET."); } } // Add control points to curve std::vector<Util::CurvePoint> controlPoints; Util::Vector startTangent(0.f, 0.f, 0.f); controlPoints.push_back(Util::CurvePoint(__position, startTangent, 0.f)); for (int i = 0; i < _goalQueue.size(); i++) { controlPoints.push_back(Util::CurvePoint(_goalQueue[i].targetLocation, _goalQueue[i].targetTangent, _goalQueue[i].targetTime)); } curve.addControlPoints(controlPoints); assert(_forward.length()!=0.0f); assert(_goalQueue.size() != 0); assert(_radius != 0.0f); }
void TattooMap::showCloseUp(int closeUpNum) { Events &events = *_vm->_events; Screen &screen = *_vm->_screen; // Reset scroll position screen._currentScroll = Common::Point(0, 0); // Get the closeup images Common::String fname = Common::String::format("res%02d.vgs", closeUpNum + 1); ImageFile pic(fname); Point32 closeUp(_data[closeUpNum].x * 100, _data[closeUpNum].y * 100); Point32 delta((SHERLOCK_SCREEN_WIDTH / 2 - closeUp.x / 100) * 100 / CLOSEUP_STEPS, (SHERLOCK_SCREEN_HEIGHT / 2 - closeUp.y / 100) * 100 / CLOSEUP_STEPS); Common::Rect oldBounds(closeUp.x / 100, closeUp.y / 100, closeUp.x / 100 + 1, closeUp.y / 100 + 1); int size = 64; int n = 256; int deltaVal = 512; bool minimize = false; int scaleVal, newSize; do { scaleVal = n; newSize = pic[0].sDrawXSize(n); if (newSize > size) { if (minimize) deltaVal /= 2; n += deltaVal; } else { minimize = true; deltaVal /= 2; n -= deltaVal; if (n < 1) n = 1; } } while (deltaVal && size != newSize); int deltaScale = (SCALE_THRESHOLD - scaleVal) / CLOSEUP_STEPS; for (int step = 0; step < CLOSEUP_STEPS; ++step) { Common::Point picSize(pic[0].sDrawXSize(scaleVal), pic[0].sDrawYSize(scaleVal)); Common::Point pt(closeUp.x / 100 - picSize.x / 2, closeUp.y / 100 - picSize.y / 2); restoreArea(oldBounds); screen._backBuffer1.transBlitFrom(pic[0], pt, false, 0, scaleVal); screen.slamRect(oldBounds); screen.slamArea(pt.x, pt.y, picSize.x, picSize.y); oldBounds = Common::Rect(pt.x, pt.y, pt.x + picSize.x + 1, pt.y + picSize.y + 1); closeUp += delta; scaleVal += deltaScale; events.wait(1); } // Handle final drawing of closeup // TODO: Handle scrolling Common::Rect r(SHERLOCK_SCREEN_WIDTH / 2 - pic[0]._width / 2, SHERLOCK_SCREEN_HEIGHT / 2 - pic[0]._height / 2, SHERLOCK_SCREEN_WIDTH / 2 - pic[0]._width / 2 + pic[0]._width, SHERLOCK_SCREEN_HEIGHT / 2 - pic[0]._height / 2 + pic[0]._height); restoreArea(oldBounds); screen._backBuffer1.transBlitFrom(pic[0], Common::Point(r.left, r.top)); screen.slamRect(oldBounds); screen.slamRect(r); events.wait(2); }
void TWindow::HandleEvent(XEvent& event) { TPoint mouse; const TPoint& scroll = GetScroll(); switch (event.type) { case Expose: { TRect r(event.xexpose.x, event.xexpose.y, event.xexpose.x + event.xexpose.width, event.xexpose.y + event.xexpose.height); if (fUpdateRegion) fUpdateRegion->Union(r); else { fUpdateRegion = new TRegion(r); fNextUpdate = sFirstUpdate; sFirstUpdate = this; } // if (event.xexpose.count == 0) // Update(); break; } case KeyPress: case KeyRelease: { TTopLevelWindow* topLevel = GetTopLevelWindow(); if (topLevel) topLevel->DispatchKeyEvent(event); break; } case ButtonPress: if (event.xbutton.button >= 1 && event.xbutton.button <= 3) { fCurrentEventTime = event.xbutton.time; mouse.Set(event.xbutton.x + scroll.h, event.xbutton.y + scroll.v); // check for multiple clicks TTime now = gApplication->GetCurrentTime(); if (now - fLastClickTime < kDoubleClickTime && abs(fLastClick.h - mouse.h) <= kDoubleClickDelta && abs(fLastClick.v - mouse.v) <= kDoubleClickDelta) ++fClickCount; else fClickCount = 1; fLastClick = mouse; fLastClickTime = now; if (IsTargetable() && event.xbutton.button != 2) RequestTarget(); HandleMouseDown(mouse, (TMouseButton)event.xbutton.button, event.xbutton.state); } else if (event.xbutton.button == 4 || event.xbutton.button == 5) { HandleScrollWheel(event.xbutton.button == 5); } break; case ButtonRelease: if (event.xbutton.button >= 1 && event.xbutton.button <= 3) { fCurrentEventTime = event.xbutton.time; mouse.Set(event.xbutton.x + scroll.h, event.xbutton.y + scroll.v); HandleMouseUp(mouse, (TMouseButton)event.xbutton.button, event.xbutton.state); } break; case EnterNotify: fCurrentEventTime = event.xcrossing.time; mouse.Set(event.xcrossing.x + scroll.h, event.xcrossing.y + scroll.v); HandleMouseEnter(mouse, event.xcrossing.state); break; case LeaveNotify: fCurrentEventTime = event.xcrossing.time; mouse.Set(event.xcrossing.x + scroll.h, event.xcrossing.y + scroll.v); HandleMouseLeave(mouse, event.xcrossing.state); break; case MotionNotify: { // avoid getting too many MotionNotify events by ignoring them if we have more in the queue XEvent testEvent; if (XPending(sDisplay) > 0 && XCheckTypedWindowEvent(sDisplay, event.xany.window, MotionNotify, &testEvent)) break; fLastMouseMovedLocation.Set(event.xmotion.x, event.xmotion.y); fLastMouseMovedModifiers = event.xmotion.state; fCurrentEventTime = event.xmotion.time; mouse.Set(event.xmotion.x + scroll.h, event.xmotion.y + scroll.v); HandleMouseMoved(mouse, event.xmotion.state); break; } case FocusIn: { if (event.xfocus.detail == NotifyAncestor || event.xfocus.detail == NotifyInferior || event.xfocus.detail == NotifyNonlinear || event.xfocus.detail == NotifyNonlinearVirtual) { if (event.xfocus.mode != NotifyGrab && event.xfocus.mode != NotifyUngrab) // these events confuse XIM, according to gdk comment { TTopLevelWindow* topLevel = GetTopLevelWindow(); if (topLevel) topLevel->GotFocus(this); break; } } } case FocusOut: { if (event.xfocus.detail == NotifyAncestor || event.xfocus.detail == NotifyInferior || event.xfocus.detail == NotifyNonlinear || event.xfocus.detail == NotifyNonlinearVirtual) { if (event.xfocus.mode != NotifyGrab && event.xfocus.mode != NotifyUngrab) // these events confuse XIM, according to gdk comment { TTopLevelWindow* topLevel = GetTopLevelWindow(); if (topLevel) topLevel->LostFocus(this); break; } } } case KeymapNotify: // printf("KeymapNotify\n"); break; case GraphicsExpose: // printf("GraphicsExpose\n"); break; case NoExpose: //mgl why are we getting these when drawing scrollbars? // printf("NoExpose\n"); break; case VisibilityNotify: fObscured = (event.xvisibility.state != VisibilityUnobscured); break; case CreateNotify: printf("CreateNotify\n"); break; case DestroyNotify: printf("DestroyNotify\n"); break; case MapNotify: DoMapped(true); break; case UnmapNotify: DoMapped(false); break; case MapRequest: printf("MapRequest\n"); break; case ReparentNotify: // printf("ReparentNotify\n"); break; case ConfigureNotify: { // we manage child window notification ourselves if (fParent == NULL) { TRect oldBounds(fBounds); fBounds.Set(event.xconfigure.x, event.xconfigure.y, event.xconfigure.x + event.xconfigure.width, event.xconfigure.y + event.xconfigure.height); NotifyBoundsChanged(oldBounds); } break; } case ConfigureRequest: printf("ConfigureRequest\n"); break; case GravityNotify: printf("GravityNotify\n"); break; case ResizeRequest: printf("ResizeRequest\n"); break; case CirculateNotify: printf("CirculateNotify\n"); break; case CirculateRequest: printf("CirculateRequest\n"); break; case PropertyNotify: printf("PropertyNotify\n"); break; case SelectionClear: { if (fIsSelectionOwner) { LostSelectionOwnership(); fIsSelectionOwner = false; } break; } case SelectionRequest: { XSelectionEvent response; response.type = SelectionNotify; response.display = event.xselectionrequest.display; response.requestor = event.xselectionrequest.requestor; response.selection = event.xselectionrequest.selection; response.target = event.xselectionrequest.target; response.property = event.xselectionrequest.property; response.time = event.xselectionrequest.time; Atom targetAtom = XInternAtom(event.xselectionrequest.display, "TARGETS", false); if (event.xselectionrequest.target == targetAtom) { Atom targets[] = { XA_STRING }; int result; result = XChangeProperty(event.xselectionrequest.display, event.xselectionrequest.requestor, event.xselectionrequest.property, event.xselectionrequest.target, 8, PropModeReplace, (const unsigned char*)targets, sizeof(targets)); if (result == BadAlloc || result == BadAtom || result == BadMatch || result == BadValue || result == BadWindow) printf ("SelectionRequest - XChangeProperty failed: %d\n", result); response.send_event = true; } else { unsigned char* data; uint32 length; Atom type = event.xselectionrequest.target; if (response.selection == XA_PRIMARY && RequestSelectionData(type, data, length)) { response.target = type; XChangeProperty(response.display, response.requestor, event.xselectionrequest.property, type, 8, PropModeReplace, data, length); free(data); } else response.property = None; } XSendEvent(sDisplay, response.requestor, false, NoEventMask, (XEvent *)&response); break; } case SelectionNotify: { if (event.xselection.property != None) { Atom type; unsigned long items, length, remaining; int actualFormat; unsigned char* data; // first compute the length XGetWindowProperty(sDisplay, fWindow, event.xselection.property, 0, 0, false, AnyPropertyType, &type, &actualFormat, &items, &length, &data); if (data) XFree(data); // now get the data XGetWindowProperty(sDisplay, fWindow, event.xselection.property, 0, length, true, AnyPropertyType, &type, &actualFormat, &items, &remaining, &data); ASSERT(remaining == 0); ReceiveSelectionData(type, data, length); XFree(data); } break; } case ColormapNotify: printf("ColormapNotify\n"); break; case ClientMessage: if ((Atom)event.xclient.data.l[0] == sDeleteWindowAtom) { Close(); } else if ((Atom)event.xclient.data.l[0] == sTakeFocusAtom) { /* TTopLevelWindow* topLevel = GetTopLevelWindow(); ASSERT(topLevel == this); topLevel->TakeFocus(); */ } else printf("unknown ClientMessage\n"); break; case MappingNotify: printf("MappingNotify\n"); break; default: break; } }
void ResizeGesture::doResize(bool scaleContent) { PageItem* currItem = m_doc->m_Selection->itemAt(0); QString targetName = Um::SelectionGroup; QPixmap* targetIcon = Um::IGroup; if (!m_doc->m_Selection->isMultipleSelection()) { targetName = currItem->getUName(); targetIcon = currItem->getUPixmap(); } if (!m_transactionStarted) { m_transactionStarted = new UndoTransaction(Um::instance()->beginTransaction(targetName, targetIcon, Um::Resize, "", Um::IResize)); // qDebug() << "ResizeGesture::doResize: begin transaction" << m_transactionStarted; } QRectF newBounds = m_bounds.normalized(); double dw = (newBounds.width() - m_extraWidth) - currItem->width(); double dh = (newBounds.height() - m_extraHeight) - currItem->height(); double dsch = 1.0; double dscw = 1.0; if (currItem->isArc()) { PageItem_Arc* item = currItem->asArc(); if (currItem->height() != 0.0) dsch = item->arcHeight / currItem->height(); if (currItem->width() != 0.0) dscw = item->arcWidth / currItem->width(); } if (m_doc->m_Selection->isMultipleSelection()) { int RotModeBack = m_doc->RotMode(); m_doc->RotMode ( 0 ); double gx, gy, gh, gw; m_doc->m_Selection->getGroupRect(&gx, &gy, &gw, &gh); QRectF oldBounds(gx, gy, gw, gh); double scx = oldBounds.width() == 0? 1.0 : (newBounds.width() - m_extraWidth) / oldBounds.width(); double scy = oldBounds.height() == 0? 1.0 : (newBounds.height() - m_extraHeight) / oldBounds.height(); //CB #3012 only scale text in a group if alt is pressed if ((currItem->itemType() == PageItem::TextFrame) && scaleContent) m_doc->scaleGroup(scx, scy, true); else m_doc->scaleGroup(scx, scy, false); double dx = newBounds.x() - oldBounds.x(); double dy = newBounds.y() - oldBounds.y(); if (dx != 0 || dy != 0) m_doc->moveGroup(dx + m_extraX, dy + m_extraY); m_doc->RotMode ( RotModeBack ); } else { if (currItem->itemType() == PageItem::ImageFrame && scaleContent) { double divX = (currItem->width() != 0) ? currItem->width() : 1.0; double divY = (currItem->height() != 0) ? currItem->height() : 1.0; double imgScX = (newBounds.width() - m_extraWidth) / divX * currItem->imageXScale(); double imgScY = (newBounds.height() - m_extraHeight) / divY * currItem->imageYScale(); // The aspect ratio has been fixed, so make the modification in the direction of the larger movement. if (currItem->keepAspectRatio() && currItem->fitImageToFrame()) { if (qAbs((newBounds.width() - m_extraWidth) - currItem->width()) > qAbs((newBounds.height() - m_extraHeight) - currItem->height())) imgScY = imgScX; else imgScX = imgScY; } currItem->setImageXYScale(imgScX, imgScY); } else if (currItem->itemType() == PageItem::ImageFrame && currItem->PictureIsAvailable) { double dx = ((newBounds.x() + m_extraX) - currItem->xPos()); double dy = ((newBounds.y() + m_extraY) - currItem->yPos()); double cosa = cos(currItem->rotation() * M_PI / 180.0); double sina = sin(currItem->rotation() * M_PI / 180.0); double xoff = -(cosa*dx + sina*dy); if (currItem->imageFlippedH()) xoff += (currItem->width() - (newBounds.width() - m_extraWidth)); double yoff = -(cosa*dy - sina*dx); if (currItem->imageFlippedV()) yoff += (currItem->height() - (newBounds.height() - m_extraHeight)); if (xoff != 0.0 || yoff != 0.0) { currItem->moveImageInFrame(xoff / currItem->imageXScale(), yoff / currItem->imageYScale()); } } // We do not want to scale the text of a linked frame // as it would alter text in other frames of the string else if((currItem->itemType() == PageItem::TextFrame) && (currItem->nextInChain() == 0) && (currItem->prevInChain() == 0) && scaleContent) { double divX = (currItem->width() != 0) ? currItem->width() : 1.0; double divY = (currItem->height() != 0) ? currItem->height() : 1.0; double txtScX = (newBounds.width() - m_extraWidth) / divX; double txtScY = (newBounds.height() - m_extraHeight) / divY; if (currItem->itemText.length() != 0) { for (int aa = 0; aa < currItem->itemText.length(); ++aa) { #if 0 // hard to decide if it’s batter to scale or to change font size currItem->itemText.item(aa)->setScaleV( qMax(qMin(qRound(currItem->itemText.item(aa)->scaleV()*txtScY), 4000), 100)); currItem->itemText.item(aa)->setScaleH( qMax(qMin(qRound(currItem->itemText.item(aa)->scaleH() * txtScX), 4000), 100)); #else currItem->itemText.item(aa)->setFontSize( qMax(qMin(currItem->itemText.item(aa)->fontSize() * txtScY, 4000.0), 1.0)); currItem->itemText.item(aa)->setScaleH( qMax(qMin(qRound(currItem->itemText.item(aa)->scaleH() * txtScX / txtScY), 4000), 100)); #endif // We need to scale the linespacing _only once_ per paragraph. if((aa == 0) || ( SpecialChars::isBreak(currItem->itemText.itemText(aa - 1).at(0)))) { ParagraphStyle ps(currItem->itemText.paragraphStyle(aa)); double oldLS(currItem->itemText.paragraphStyle(aa).lineSpacing()); ps.setLineSpacing(qMax(qRound(oldLS * txtScY), 1)); currItem->itemText.setStyle(aa,ps); } } } } currItem->setXYPos(newBounds.x() + m_extraX, newBounds.y() + m_extraY); currItem->setWidth(newBounds.width() - m_extraWidth); currItem->setHeight(newBounds.height() - m_extraHeight); currItem->updateClip(); if (currItem->isArc()) { PageItem_Arc* item = currItem->asArc(); item->arcWidth += dw * dscw; item->arcHeight += dh * dsch; item->recalcPath(); FPoint tp2(getMinClipF(&currItem->PoLine)); currItem->PoLine.translate(-tp2.x(), -tp2.y()); m_doc->AdjustItemSize(currItem); } if (currItem->isSpiral()) { PageItem_Spiral* item = currItem->asSpiral(); item->recalcPath(); } // rotation does not change } m_origBounds = m_bounds; }