Example #1
0
bool GiGraphics::drawRect(const GiContext* ctx, const Box2d& rect, 
                          bool modelUnit)
{
    if (rect.isEmpty() && ctx && m_impl->canvas) {
        rawRect(ctx, 0, 0, 0, 0);
        return false;
    }
    Point2d points[4] = {
        rect.leftBottom(), rect.rightBottom(), 
        rect.rightTop(), rect.leftTop()
    };
    return !rect.isEmpty() && drawPolygon(ctx, 4, points, modelUnit);
}
Example #2
0
Box2d GiTransform::setWorldLimits(const Box2d& rect)
{
    Box2d ret = m_impl->rectLimitsW;
    m_impl->rectLimitsW = rect.isEmpty() ? Box2d(Point2d::kOrigin(), 2e5f, 2e5f) : rect;
    m_impl->rectLimitsW.normalize();
    return ret;
}
Example #3
0
float mgnear::roundRectHit(
    const Box2d& rect, float rx, float ry, 
    const Point2d& pt, float tol, Point2d& nearpt, int& segment)
{
    rx = fabsf(rx);
    if (ry < _MGZERO)
        ry = rx;
    rx = mgMin(rx, rect.width() * 0.5f);
    ry = mgMin(ry, rect.height() * 0.5f);
    segment = -1;
    
    Point2d ptTemp, ptTemp2;
    float dist, distMin = _FLT_MAX;
    Point2d pts[8];
    const Box2d rectTol (pt, 2 * tol, 2 * tol);
    
    // 顶边上的两个圆弧切点,左,右
    pts[0] = RoundRectTan(0, 1, rect, rx);
    pts[1] = RoundRectTan(1, 0, rect, rx);
    
    // 右边上的两个圆弧切点,上,下
    pts[2] = RoundRectTan(1, 2, rect, ry);
    pts[3] = RoundRectTan(2, 1, rect, ry);
    
    // 底边上的两个圆弧切点,右,左
    pts[4] = RoundRectTan(2, 3, rect, rx);
    pts[5] = RoundRectTan(3, 2, rect, rx);
    
    // 左边上的两个圆弧切点,下,上
    pts[6] = RoundRectTan(3, 0, rect, ry);
    pts[7] = RoundRectTan(0, 3, rect, ry);
    
    for (int i = 0; i < 4; i++)
    {
        Box2d rcLine (pts[2 * i], pts[2 * i + 1]);
        if (rcLine.isEmpty() || rectTol.isIntersect(rcLine))
        {
            dist = mglnrel::ptToLine(pts[2 * i], pts[2 * i + 1], pt, ptTemp);
            if (dist <= tol && dist < distMin)
            {
                distMin = dist;
                nearpt = ptTemp;
                segment = 4 + i;
            }
        }
    }
    
    if (rx > _MGZERO && ry > _MGZERO)
    {
        _RoundRectHit(rect, rx, ry, pt, tol, 
            rectTol, pts, distMin, nearpt, segment);
    }

    return distMin;
}
Example #4
0
bool GiGraphics::drawRoundRect(const GiContext* ctx, 
                               const Box2d& rect, float rx, float ry, 
                               bool modelUnit)
{
    if (m_impl->drawRefcnt == 0 || rect.isEmpty())
        return false;
    GiLock lock (&m_impl->drawRefcnt);
    bool ret = false;

    if (ry < _MGZERO)
        ry = rx;

    if (!DRAW_RECT(m_impl, modelUnit).isIntersect(rect))  // 全部在显示区域外
        return false;

    if (rx < _MGZERO)
    {
        Point2d points[4] = {
            rect.leftBottom(), rect.rightBottom(), 
            rect.rightTop(), rect.leftTop()
        };
        return drawPolygon(ctx, 4, points);
    }
    else
    {
        Point2d points[16];

        mgRoundRectToBeziers(points, rect, rx, ry);
        S2D(xf(), modelUnit).TransformPoints(16, points);

        ret = rawBeginPath();
        if (ret)
        {
            ret = rawMoveTo(points[0].x, points[0].y);
            ret = rawBezierTo(&points[1], 3);

            ret = rawLineTo(points[4].x, points[4].y);
            ret = rawBezierTo(&points[5], 3);

            ret = rawLineTo(points[8].x, points[8].y);
            ret = rawBezierTo(&points[9], 3);

            ret = rawLineTo(points[12].x, points[12].y);
            ret = rawBezierTo(&points[13], 3);

            ret = rawClosePath();
            ret = rawEndPath(ctx, true);
        }
    }

    return ret;
}
Example #5
0
void MgCmdManagerImpl::getBoundingBox(Box2d& box, const MgMotion* sender)
{
    MgCommand* cmd = sender->cmds()->getCommand();
    Box2d selbox;

    if (cmd && strcmp(cmd->getName(), MgCmdSelect::Name()) == 0) {
        MgCmdSelect* sel = (MgCmdSelect*)cmd;
        selbox = sel->getBoundingBox(sender);
    }

    box = selbox.isEmpty() ? Box2d(sender->pointM, 0, 0) : selbox;
    box *= sender->view->xform()->modelToDisplay();
    box.normalize();
}
Example #6
0
bool GiGraphics::drawRoundRect(const GiContext* ctx, 
                               const Box2d& rect, float rx, float ry, 
                               bool modelUnit)
{
    if (rect.isEmpty() || isStopping())
        return false;
    bool ret = false;

    if (ry < _MGZERO)
        ry = rx;

    if (!DRAW_RECT(m_impl, modelUnit).isIntersect(rect))  // 全部在显示区域外
        return false;

    if (rx < _MGZERO) {
        Point2d points[4] = {
            rect.leftBottom(), rect.rightBottom(), 
            rect.rightTop(), rect.leftTop()
        };
        return drawPolygon(ctx, 4, points);
    } else {
        Point2d pxs[16];

        mgcurv::roundRectToBeziers(pxs, rect, rx, ry);
        S2D(xf(), modelUnit).transformPoints(16, pxs);

        ret = rawBeginPath();
        if (ret) {
            rawMoveTo(pxs[0].x, pxs[0].y);
            rawBezierTo(pxs[1].x, pxs[1].y, pxs[2].x, pxs[2].y, pxs[3].x, pxs[3].y);

            rawLineTo(pxs[4].x, pxs[4].y);
            rawBezierTo(pxs[5].x, pxs[5].y, pxs[6].x, pxs[6].y, pxs[7].x, pxs[7].y);

            rawLineTo(pxs[8].x, pxs[8].y);
            rawBezierTo(pxs[9].x, pxs[9].y, pxs[10].x, pxs[10].y, pxs[11].x, pxs[11].y);

            rawLineTo(pxs[12].x, pxs[12].y);
            rawBezierTo(pxs[13].x, pxs[13].y, pxs[14].x, pxs[14].y, pxs[15].x, pxs[15].y);

            rawClosePath();
            ret = rawEndPath(ctx, true);
        }
    }

    return ret;
}
Example #7
0
static bool AdjustCenterIn(bool adjust, const Box2d& box, const Box2d& limitsW, 
                           Point2d &ptW, float halfw, float halfh)
{
    Box2d rectW(limitsW);
    rectW.inflate(2);

    if (!limitsW.isEmpty() && !rectW.contains(box)) {
        if (adjust) {
            AdjustCenterW(ptW, halfw, halfh, rectW);
        }
        else {
            return false;
        }
    }

    return true;
}
Example #8
0
void mgnear::moveRectHandle(Box2d& rect, int index, 
                              const Point2d& pt, bool lockCornerScale)
{
    Point2d pts[4];

    for (int i = 0; i < 4; i++)
        mgnear::getRectHandle(rect, index / 4 * 4 + i, pts[i]);
    pts[index % 4] = pt;

    if (index >= 0 && index < 4)
    {
        Point2d pt1(pt);
        
        if (lockCornerScale && !rect.isEmpty()) {
            Point2d& pt2 = pts[(index + 2) % 4];
            float w = fabsf(pt2.x - pt.x);
            float h = fabsf(pt2.y - pt.y);
            
            if (w * rect.height() > h * rect.width())
                h = w * rect.height() / rect.width();
            else
                w = h * rect.width() / rect.height();
            
            pt1.x = pt2.x + w * (pt2.x > pt.x ? -1.f : 1.f);
            pt1.y = pt2.y + h * (pt2.y > pt.y ? -1.f : 1.f);
        }
        if (index % 2 == 0)
        {
            pts[(index + 1) % 4].y = pt1.y;
            pts[(index + 3) % 4].x = pt1.x;
        }
        else
        {
            pts[(index + 1) % 4].x = pt1.x;
            pts[(index + 3) % 4].y = pt1.y;
        }
        rect.set(4, pts);
    }
    else if (index >= 4 && index < 8)
    {
        rect.set(pts[3].x, pts[2].y, pts[1].x, pts[0].y);
    }
}
Example #9
0
    Vector2d moveActionsInView(Box2d& rect)
    {
        Vector2d off;
        Box2d viewrect(0.f, 0.f, (float)xform()->getWidth(), (float)xform()->getHeight());

        if (!rect.isEmpty() && !viewrect.contains(rect)) {
            if (rect.xmin < 0) {
                off.x = -rect.xmin;
            }
            else if (rect.xmax > viewrect.xmax) {
                off.x = viewrect.xmax - rect.xmax;
            }

            if (rect.ymin < 0) {
                off.y = -rect.ymin;
            }
            else if (rect.ymax > viewrect.ymax) {
                off.y = viewrect.ymax - rect.ymax;
            }
        }

        return off;
    }
Example #10
0
bool GiTransform::zoomTo(const Box2d& rectWorld, const RECT_2D* rcTo, bool adjust)
{
    // 如果图形范围的宽或高接近于零,就返回
    if (rectWorld.isEmpty())
        return false;

    // 计算像素到毫米的比例
    const float d2mmX = m_impl->viewScale / m_impl->w2dx;
    const float d2mmY = m_impl->viewScale / m_impl->w2dy;

    // 计算目标窗口区域(毫米)
    float w = 0, h = 0;
    Point2d ptCen;

    if (rcTo != NULL) {
        w = fabsf(static_cast<float>(rcTo->right - rcTo->left));
        h = fabsf(static_cast<float>(rcTo->bottom - rcTo->top));
        ptCen.x = (rcTo->left + rcTo->right) * 0.5f;
        ptCen.y = (rcTo->top + rcTo->bottom) * 0.5f;
    }
    if (w < 4 || h < 4) {
        w = (float)m_impl->cxWnd;
        h = (float)m_impl->cyWnd;
        ptCen.set(w * 0.5f, h * 0.5f);
        w -= 8;
        h -= 8;
    }
    if (w < 4 || h < 4)
        return false;
    w *= d2mmX;
    h *= d2mmY;
    ptCen.scaleBy(d2mmX, d2mmY);

    // 计算新显示比例 (中心不变,缩小窗口区域使得宽高比例和图形范围相同)
    float scale;
    if (h * rectWorld.width() > w * rectWorld.height()) {
        //h = w * rectWorld.height() / rectWorld.width();
        scale = w / rectWorld.width();
    }
    else {
        //w = h * rectWorld.width() / rectWorld.height();
        scale = h / rectWorld.height();
    }

    // 检查显示比例
    if (!adjust && ScaleOutRange(scale, m_impl))
        return false;
    scale = mgMax(scale, m_impl->minViewScale);
    scale = mgMin(scale, m_impl->maxViewScale);

    // 计算在新显示比例下显示窗口中心的世界坐标
    Point2d ptW;
    ptW.x = rectWorld.center().x + (m_impl->cxWnd * d2mmX * 0.5f - ptCen.x) / scale;
    ptW.y = rectWorld.center().y - (m_impl->cyWnd * d2mmY * 0.5f - ptCen.y) / scale;

    // 检查新显示比例下显示窗口的世界坐标范围是否在极限范围内
    float halfw = m_impl->cxWnd * d2mmX  / scale * 0.5f;
    float halfh = m_impl->cyWnd * d2mmY  / scale * 0.5f;
    Box2d box (ptW, 2 * halfw, 2 * halfh);

    if (!AdjustCenterIn(adjust, box, m_impl->rectLimitsW, ptW, halfw, halfh)) {
        return false;
    }

    return m_impl->zoomNoAdjust(ptW, scale);
}
Example #11
0
bool giPrintSetup(GiTransform& xf, HDC hdc, const Box2d& rectShow, bool bWorldRect,
                  const RECT* margin, float scale,
                  float offsetX, float offsetY)
{
    if (hdc == NULL || rectShow.isEmpty())
        return false;

    int dpix   = GetDeviceCaps(hdc, LOGPIXELSX);        // 每英寸的像素数
    int dpiy   = GetDeviceCaps(hdc, LOGPIXELSY);        // 每英寸的像素数
    int width  = GetDeviceCaps(hdc, PHYSICALWIDTH);     // 页面宽,像素
    int height = GetDeviceCaps(hdc, PHYSICALHEIGHT);    // 页面高,像素
    int cx     = GetDeviceCaps(hdc, HORZRES);           // 可打印宽度,像素
    int cy     = GetDeviceCaps(hdc, VERTRES);           // 可打印高度,像素
    int ml     = GetDeviceCaps(hdc, PHYSICALOFFSETX);   // 左最小边距,像素
    int mt     = GetDeviceCaps(hdc, PHYSICALOFFSETY);   // 上最小边距,像素
    int mr     = width - cx - ml;                       // 右最小边距,像素
    int mb     = height - cy - mt;                      // 下最小边距,像素
    RECT rc    = { 0, 0, cx, cy };                      // 纸上打印范围,像素

    if (margin != NULL)     // 指定了页边距
    {
        int n;
        if (ml < (n = MulDiv(margin->left, dpix, 2540)))
            rc.left += n - ml;
        if (mt < (n = MulDiv(margin->top, dpiy, 2540)))
            rc.top += n - mt;
        if (mr < (n = MulDiv(margin->right, dpix, 2540)))
            rc.right -= n - mr;
        if (mb < (n = MulDiv(margin->bottom, dpiy, 2540)))
            rc.bottom -= n - mb;
        if (rc.right - rc.left < 10)
        {
            rc.left = 0;
            rc.right = cx;
        }
        if (rc.bottom - rc.top < 10)
        {
            rc.top = 0;
            rc.bottom = cy;
        }
    }
    ::InflateRect(&rc, -1, -1);     // 缩小纸上打印范围,以便放缩后不丢失像素

    xf.setWndSize(cx, cy);
    xf.setResolution((float)dpix, (float)dpiy);

    Box2d rectShowW = rectShow;
    if (!bWorldRect)
        rectShowW *= xf.modelToWorld();

    Box2d rectOld = xf.setWorldLimits(Box2d());
    RECT2D rc2d(giConvertRect(rc));
    bool ret = xf.zoomTo(rectShowW, &rc2d, true);
    if (scale >= xf.getMinViewScale() && scale <= xf.getMaxViewScale())
    {
        ret = ret && xf.zoomScale(scale, NULL, true);
        xf.zoom(xf.getCenterW() - Vector2d(offsetX, offsetY), xf.getViewScale());
    }
    xf.setWorldLimits(rectOld);

    return ret;
}
Example #12
0
bool MgCmdManagerImpl::showInSelect(const MgMotion* sender, int selState, const MgShape* shape, const Box2d& selbox)
{
    if (sender->view->getCmdSubject()->selectActionsNeedHided(sender)) {
        return false;
    }
    
    int actions[12];
    int n = 0;
    bool isslines = (shape && selState == kMgSelOneShape
                     && shape->shapec()->isKindOf(kMgShapeSplines));
    bool isOpenLines = (shape && selState == kMgSelOneShape
                        && shape->shapec()->isKindOf(kMgShapeLines)
                        && !shape->shapec()->isClosed());
    bool locked = shape && shape->shapec()->getFlag(kMgShapeLocked);
    bool fixedLength = shape && shape->shapec()->getFlag(kMgFixedLength);
    
    switch (selState) {
        case kMgSelNone:
            break;
            
        case kMgSelMultiShapes:
            if (shape && shape->getParent()
                && shape->getParent()->getOwner()->isKindOf(kMgShapeDoc)) {
                actions[n++] = kMgActionGroup;
            }
        case kMgSelOneShape:
            if (!locked && !sender->view->useFinger()) {
                actions[n++] = kMgActionDelete;
            }
            actions[n++] = kMgActionClone;
            if (!locked && shape
                && (shape->shapec()->isKindOf(kMgShapeImage)
                    || shape->shapec()->isKindOf(kMgShapeLine))) {
                actions[n++] = fixedLength ? kMgActionFreeLength : kMgActionFixedLength;
            }
            actions[n++] = locked ? kMgActionUnlocked : kMgActionLocked;
            if (selState == kMgSelOneShape && !locked) {
                actions[n++] = kMgActionEditVertex;
            }
            else {
                //actions[n++] = kMgActionSelReset;
            }
            if (selState == kMgSelOneShape
                && shape && shape->shapec()->isClosed()
                && !shape->shapec()->getFlag(kMgRotateDisnable)
                && !shape->shapec()->getFlag(kMgShapeLocked)
                && (shape->shapec()->isKindOf(kMgShapeParallel)
                    || shape->shapec()->isKindOf(kMgShapeLines)) ) {
                actions[n++] = kMgActionOverturn;
            }
            break;
            
        case kMgSelVertexes:
            if ((isslines || isOpenLines)
                && shape && !shape->shapec()->getFlag(kMgShapeLocked)) {
                //actions[n++] = closed ? kMgActionOpened : kMgActionClosed;
                actions[n++] = kMgActionAddVertex;
            }
            if (!locked && shape && shape->shapec()->isKindOf(kMgShapeLine)) {
                actions[n++] = fixedLength ? kMgActionFreeLength : kMgActionFixedLength;
            }
            //actions[n++] = locked ? kMgActionUnlocked : kMgActionLocked;
            actions[n++] = kMgActionHideVertex;
            break;
            
        case kMgSelVertex:
            if ((isslines || isOpenLines)
                && shape && !shape->shapec()->getFlag(kMgShapeLocked)) {
                //actions[n++] = closed ? kMgActionOpened : kMgActionClosed;
                actions[n++] = kMgActionDelVertex;
            }
            if (!locked && shape && shape->shapec()->isKindOf(kMgShapeLine)) {
                actions[n++] = fixedLength ? kMgActionFreeLength : kMgActionFixedLength;
            }
            //actions[n++] = locked ? kMgActionUnlocked : kMgActionLocked;
            actions[n++] = kMgActionHideVertex;
            break;
            
        case kMgSelDraw:
            break;
    }
    
    if (selState > kMgSelNone && selState <= kMgSelVertex && shape) {
        mgvector<int> arr(actions, sizeof(actions)/sizeof(actions[0]));
        n = sender->view->getCmdSubject()->addShapeActions(sender, arr, n, shape);
        for (int i = 0; i < n; i++) {
            actions[i] = arr.get(i);
        }

        if (shape->shapec()->isKindOf(kMgShapeGroup)
            && sender->view->shapeCanUngroup(shape)) {
            actions[n++] = kMgActionUngroup;
        }
    }
    
    actions[n++] = 0;
    
    if (!selbox.isEmpty()) {
        sender->view->redraw();
    }
    
    Box2d box(selbox.isEmpty() ? Box2d(sender->pointM, 0, 0) : selbox);
    box *= sender->view->xform()->modelToDisplay();
    
    return sender->view->showContextActions(selState, actions, box, shape);
}