Beispiel #1
0
bool tutorial_game::init()
{
    // TODO: clean up old tutorial

 calendar::turn = HOURS(12); // Start at noon
 for( auto &elem : tutorials_seen )
     elem = false;
// Set the scent map to 0
 for (int i = 0; i < SEEX * MAPSIZE; i++) {
  for (int j = 0; j < SEEX * MAPSIZE; j++)
   g->scent(i, j) = 0;
 }
 g->temperature = 65;
// We use a Z-factor of 10 so that we don't plop down tutorial rooms in the
// middle of the "real" game world
 g->u.normalize();
 g->u.str_cur = g->u.str_max;
 g->u.per_cur = g->u.per_max;
 g->u.int_cur = g->u.int_max;
 g->u.dex_cur = g->u.dex_max;

 for (int i = 0; i < num_hp_parts; i++) {
     g->u.hp_cur[i] = g->u.hp_max[i];
 }

 //~ default name for the tutorial
 g->u.name = _("John Smith");
 g->u.prof = profession::generic();
    int lx = 50, ly = 50; // overmap terrain coordinates
    g->cur_om = &overmap_buffer.get(0, 0);
    for (int i = 0; i < OMAPX; i++) {
        for (int j = 0; j < OMAPY; j++) {
            g->cur_om->ter( i, j, -1 ) = "rock";
            // Start with the overmap revealed
            g->cur_om->seen( i, j, 0 ) = true;
        }
    }
    g->cur_om->ter(lx, ly, 0) = "tutorial";
    g->cur_om->ter(lx, ly, -1) = "tutorial";
    g->cur_om->clear_mon_groups();
    // to submap coordinates as it is supposed to be
    g->levx = lx * 2;
    g->levy = ly * 2;

 g->u.toggle_trait("QUICK");
 item lighter("lighter", 0);
 lighter.invlet = 'e';
 g->u.inv.add_item(lighter);
 g->u.skillLevel("gun").level(5);
 g->u.skillLevel("melee").level(5);
 g->m.load(g->levx, g->levy, 0, true, g->cur_om);
 g->levz = 0;
 g->u.setx( 2 );
 g->u.sety( 4 );

 // This shifts the view to center the players pos
 g->update_map(&(g->u));
 return true;
}
Beispiel #2
0
//====================
	void bevel(bool sunken, int pos)
	{
		if (--pos < 0) return;
		int w = width, h = height;
		int nx = w - 2*pos - 1;
		int ny = h - 2*pos - 1;
		if (nx <= 0 || ny <= 0) return;

		int f1 = DELTA_BEVEL;
		int f2 = DELTA_BEVELCORNER;

		if (sunken) f1 = -f1, f2 = -f2;
		make_delta_table (f1);

		unsigned char *p;
		int d, e, n;

		p = pixels + (pos + w * pos) * 4;

		d = ny * w * 4;
		e = 4;
		n = nx;
		while (--n)
		{
			p += e;
			darker(p);
			lighter(p+d);
		}
		p += e;
		modify(p,-f2);  // bottom-right corner pixel

		d = nx * 4;
		e = w * 4;
		n = ny;
		while (--n)
		{
			p += e;
			darker(p);
			lighter(p-d);
		}
		p += e;
		modify(p-d, f2); // top-left corner pixel
	}
bool tutorial_game::init()
{
    // TODO: clean up old tutorial

    calendar::turn = HOURS( 12 ); // Start at noon
    for( auto &elem : tutorials_seen ) {
        elem = false;
    }
    g->scent.reset();
    g->temperature = 65;
    // We use a Z-factor of 10 so that we don't plop down tutorial rooms in the
    // middle of the "real" game world
    g->u.normalize();
    g->u.str_cur = g->u.str_max;
    g->u.per_cur = g->u.per_max;
    g->u.int_cur = g->u.int_max;
    g->u.dex_cur = g->u.dex_max;

    for( int i = 0; i < num_hp_parts; i++ ) {
        g->u.hp_cur[i] = g->u.hp_max[i];
    }

    const oter_id rock( "rock" );
    //~ default name for the tutorial
    g->u.name = _( "John Smith" );
    g->u.prof = profession::generic();
    // overmap terrain coordinates
    const int lx = 50;
    const int ly = 50;
    auto &starting_om = overmap_buffer.get( 0, 0 );
    for( int i = 0; i < OMAPX; i++ ) {
        for( int j = 0; j < OMAPY; j++ ) {
            starting_om.ter( i, j, -1 ) = rock;
            // Start with the overmap revealed
            starting_om.seen( i, j, 0 ) = true;
        }
    }
    starting_om.ter( lx, ly, 0 ) = oter_id( "tutorial" );
    starting_om.ter( lx, ly, -1 ) = oter_id( "tutorial" );
    starting_om.clear_mon_groups();

    g->u.toggle_trait( trait_id( "QUICK" ) );
    item lighter( "lighter", 0 );
    lighter.invlet = 'e';
    g->u.inv.add_item( lighter, true, false );
    g->u.set_skill_level( skill_id( "gun" ), 5 );
    g->u.set_skill_level( skill_id( "melee" ), 5 );
    g->load_map( omt_to_sm_copy( tripoint( lx, ly, 0 ) ) );
    g->u.setx( 2 );
    g->u.sety( 4 );

    // This shifts the view to center the players pos
    g->update_map( g->u );
    return true;
}
Beispiel #4
0
CGColor CGColor::darker(float factor)
{
    if ( factor <= 0 )				// invalid darkness factor
        return *this;
    else if ( factor < 100 )			// makes color lighter
        return lighter( 10000.0/factor );
    float h, s, v;
    getHSV( h, s, v );
    v = (v*100.0)/factor;
    CGColor c;
    c.setFromHSV( h, s, v );
    return c;
}
Beispiel #5
0
//====================
void bevel(bool sunken, int pos, int exception)
{
    if (--pos < 0) return;
    int w = width, h = height;
    int nx = w - 2*pos - 1;
    int ny = h - 2*pos - 1;
    if (nx <= 0 || ny <= 0) return;

    int f1 = DELTA_BEVEL;
    int f2 = DELTA_BEVELCORNER;

    if (sunken) f1 = -f1, f2 = -f2;
    make_delta_table (f1);

    unsigned char *p; int d, e, n;

    p = pixels + (pos + w * pos) * 4;

    d = ny * w * 4; e = 4; n = nx;
    if (exception == BEVEL_EXCEPT_LEFT) darker(p);
    while (--n) {
        p += e;
        if (exception != BEVEL_EXCEPT_BOTTOM) darker(p);
        if (exception != BEVEL_EXCEPT_TOP)    lighter(p+d);
    }

    p += e;
    if (exception == BEVEL_EXCEPT_BOTTOM)
        darker(p);
    else if (exception == BEVEL_EXCEPT_RIGHT)
        darker(p), lighter(p+d);
    else modify(p,-f2);  // bottom-right corner pixel

    d = nx * 4; e = w * 4; n = ny;
    if (exception == BEVEL_EXCEPT_BOTTOM) lighter(p-d);
    while (--n) {
        p += e;
        if (exception != BEVEL_EXCEPT_RIGHT) darker(p);
        if (exception != BEVEL_EXCEPT_LEFT)  lighter(p-d);
    }

    p += e;
    if (exception == BEVEL_EXCEPT_TOP)
        darker(p), lighter(p-d);
    else if (exception == BEVEL_EXCEPT_LEFT)
        lighter(p-d);
    else
        modify(p-d, f2); // top-left corner pixel
}
Beispiel #6
0
	void Window::drawWindow(Renderer2D &out, IRect rect, FColor color, int outline) {
		FColor lighter(color.rgb() * 1.2f, color.a);
		FColor darker(color.rgb() * 0.8f, color.a);
		int aoutline = fwk::abs(outline);

		if(outline) {
			int2 hsize(rect.width(), aoutline);
			int2 vsize(aoutline, rect.height());

			FColor col1 = outline < 0? darker : lighter;
			out.addFilledRect(IRect(rect.min, rect.min + hsize), col1);
			out.addFilledRect(IRect(rect.min, rect.min + vsize), col1);

			int2 p1(rect.min.x, rect.max.y - aoutline);
			int2 p2(rect.max.x - aoutline, rect.min.y);
			FColor col2 = outline < 0? lighter : darker;
			out.addFilledRect(IRect(p1, p1 + hsize), col2);
			out.addFilledRect(IRect(p2, p2 + vsize), col2);
		}

		int2 off(aoutline, aoutline);
		out.addFilledRect(inset(rect, off, off), color);
	}
void ManhattanStyle::drawControl(ControlElement element, const QStyleOption *option,
                                 QPainter *painter, const QWidget *widget) const {
    if (!panelWidget(widget))
        return d->style->drawControl(element, option, painter, widget);

    switch (element) {
    case CE_MenuBarItem:
        painter->save();
        if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
            QColor highlightOutline = StyleHelper::borderColor().lighter(120);
            bool act = mbi->state & State_Selected && mbi->state & State_Sunken;
            bool dis = !(mbi->state & State_Enabled);
            StyleHelper::menuGradient(painter, option->rect, option->rect);
            QStyleOptionMenuItem item = *mbi;
            item.rect = mbi->rect;
            QPalette pal = mbi->palette;
            pal.setBrush(QPalette::ButtonText, dis ? Qt::gray : Qt::black);
            item.palette = pal;
            QCommonStyle::drawControl(element, &item, painter, widget);
            QRect r = option->rect;

            if (act) {
                // Fill|
                QColor baseColor = StyleHelper::baseColor();
                QLinearGradient grad(option->rect.topLeft(), option->rect.bottomLeft());
                grad.setColorAt(0, baseColor.lighter(120));
                grad.setColorAt(1, baseColor.lighter(130));
                painter->fillRect(option->rect.adjusted(1, 1, -1, 0), grad);

                // Outline
                painter->setPen(QPen(highlightOutline, 0));
                painter->drawLine(QPoint(r.left(), r.top() + 1), QPoint(r.left(), r.bottom()));
                painter->drawLine(QPoint(r.right(), r.top() + 1), QPoint(r.right(), r.bottom()));
                painter->drawLine(QPoint(r.left() + 1, r.top()), QPoint(r.right() - 1, r.top()));
                highlightOutline.setAlpha(60);
                painter->setPen(QPen(highlightOutline, 0));
                painter->drawPoint(r.topLeft());
                painter->drawPoint(r.topRight());

                QPalette pal = mbi->palette;
                uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
                if (!styleHint(SH_UnderlineShortcut, mbi, widget))
                    alignment |= Qt::TextHideMnemonic;
                pal.setBrush(QPalette::Text, dis ? Qt::gray : QColor(0, 0, 0, 60));
                drawItemText(painter, item.rect.translated(0, 1), alignment, pal, mbi->state & State_Enabled, mbi->text, QPalette::Text);
                pal.setBrush(QPalette::Text, dis ? Qt::gray : Qt::white);
                drawItemText(painter, item.rect, alignment, pal, mbi->state & State_Enabled, mbi->text, QPalette::Text);
            }
        }
        painter->restore();
        break;

    case CE_ComboBoxLabel:
        if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
            if (panelWidget(widget)) {
                QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
                QPalette customPal = cb->palette;

                if (!cb->currentIcon.isNull()) {
                    QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal
                                       : QIcon::Disabled;
                    QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode);
                    QRect iconRect(editRect);
                    iconRect.setWidth(cb->iconSize.width() + 4);
                    iconRect = alignedRect(cb->direction,
                                           Qt::AlignLeft | Qt::AlignVCenter,
                                           iconRect.size(), editRect);
                    if (cb->editable)
                        painter->fillRect(iconRect, customPal.brush(QPalette::Base));
                    drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);

                    if (cb->direction == Qt::RightToLeft)
                        editRect.translate(-4 - cb->iconSize.width(), 0);
                    else
                        editRect.translate(cb->iconSize.width() + 4, 0);

                    // Reserve some space for the down-arrow
                    editRect.adjust(0, 0, -13, 0);
                }

                customPal.setBrush(QPalette::All, QPalette::ButtonText, QColor(0, 0, 0, 70));

                QString text = option->fontMetrics.elidedText(cb->currentText, Qt::ElideRight, editRect.width());
                drawItemText(painter, editRect.translated(0, 1),
                             visualAlignment(option->direction, Qt::AlignLeft | Qt::AlignVCenter),
                             customPal, cb->state & State_Enabled, text, QPalette::ButtonText);
                customPal.setBrush(QPalette::All, QPalette::ButtonText, StyleHelper::panelTextColor());
                drawItemText(painter, editRect,
                             visualAlignment(option->direction, Qt::AlignLeft | Qt::AlignVCenter),
                             customPal, cb->state & State_Enabled, text, QPalette::ButtonText);
            } else {
                d->style->drawControl(element, option, painter, widget);
            }
        }
        break;

    case CE_SizeGrip: {
        painter->save();
        QColor dark = Qt::white;
        dark.setAlphaF(0.1);
        int x, y, w, h;
        option->rect.getRect(&x, &y, &w, &h);
        int sw = qMin(h, w);
        if (h > w)
            painter->translate(0, h - w);
        else
            painter->translate(w - h, 0);
        int sx = x;
        int sy = y;
        int s = 4;
        painter->setPen(dark);
        if (option->direction == Qt::RightToLeft) {
            sx = x + sw;
            for (int i = 0; i < 4; ++i) {
                painter->drawLine(x, sy, sx, sw);
                sx -= s;
                sy += s;
            }
        } else {
            for (int i = 0; i < 4; ++i) {
                painter->drawLine(sx, sw, sw, sy);
                sx += s;
                sy += s;
            }
        }
        painter->restore();
    }
    break;

    case CE_MenuBarEmptyArea: {
        StyleHelper::menuGradient(painter, option->rect, option->rect);
        painter->save();
        painter->setPen(StyleHelper::borderColor());
        painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
        painter->restore();
    }
    break;

    case CE_ToolBar: {
        QString key;
        key.sprintf("mh_toolbar %d %d %d", option->rect.width(), option->rect.height(), StyleHelper::baseColor().rgb());;

        QPixmap pixmap;
        QPainter *p = painter;
        QRect rect = option->rect;
        if (StyleHelper::usePixmapCache() && !QPixmapCache::find(key, pixmap)) {
            pixmap = QPixmap(option->rect.size());
            p = new QPainter(&pixmap);
            rect = QRect(0, 0, option->rect.width(), option->rect.height());
        }

        bool horizontal = option->state & State_Horizontal;
        // Map offset for global window gradient
        QPoint offset = widget->window()->mapToGlobal(option->rect.topLeft()) -
                        widget->mapToGlobal(option->rect.topLeft());
        QRect gradientSpan;
        if (widget) {
            gradientSpan = QRect(offset, widget->window()->size());
        }
        if (horizontal)
            StyleHelper::horizontalGradient(p, gradientSpan, rect);
        else
            StyleHelper::verticalGradient(p, gradientSpan, rect);

        painter->setPen(StyleHelper::borderColor());

        if (horizontal) {
            // Note: This is a hack to determine if the
            // toolbar should draw the top or bottom outline
            // (needed for the find toolbar for instance)
            QColor lighter(255, 255, 255, 40);
            if (widget && widget->property("topBorder").toBool()) {
                p->drawLine(rect.topLeft(), rect.topRight());
                p->setPen(lighter);
                p->drawLine(rect.topLeft() + QPoint(0, 1), rect.topRight() + QPoint(0, 1));
            } else {
                p->drawLine(rect.bottomLeft(), rect.bottomRight());
                p->setPen(lighter);
                p->drawLine(rect.topLeft(), rect.topRight());
            }
        } else {
            p->drawLine(rect.topLeft(), rect.bottomLeft());
            p->drawLine(rect.topRight(), rect.bottomRight());
        }

        if (StyleHelper::usePixmapCache() && !QPixmapCache::find(key, pixmap)) {
            painter->drawPixmap(rect.topLeft(), pixmap);
            p->end();
            delete p;
            QPixmapCache::insert(key, pixmap);
        }
    }
    break;

    default:
        d->style->drawControl(element, option, painter, widget);
        break;
    }
}
void ManhattanStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
                                   QPainter *painter, const QWidget *widget) const {
    if (!panelWidget(widget))
        return d->style->drawPrimitive(element, option, painter, widget);

    bool animating = (option->state & State_Animating);
    int state = option->state;
    QRect rect = option->rect;
    QRect oldRect;
    QRect newRect;
    if (widget && (element == PE_PanelButtonTool) && !animating) {
        QWidget *w = const_cast<QWidget *> (widget);
        int oldState = w->property("_q_stylestate").toInt();
        oldRect = w->property("_q_stylerect").toRect();
        newRect = w->rect();
        w->setProperty("_q_stylestate", (int)option->state);
        w->setProperty("_q_stylerect", w->rect());

        // Determine the animated transition
        bool doTransition = ((state & State_On)         != (oldState & State_On)     ||
                             (state & State_MouseOver)  != (oldState & State_MouseOver));
        if (oldRect != newRect) {
            doTransition = false;
            d->animator.stopAnimation(widget);
        }

        if (doTransition) {
            QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
            QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
            Animation *anim = d->animator.widgetAnimation(widget);
            QStyleOption opt = *option;
            opt.state = (QStyle::State)oldState;
            opt.state |= (State)State_Animating;
            startImage.fill(0);
            Transition *t = new Transition;
            t->setWidget(w);
            QPainter startPainter(&startImage);
            if (!anim) {
                drawPrimitive(element, &opt, &startPainter, widget);
            } else {
                anim->paint(&startPainter, &opt);
                d->animator.stopAnimation(widget);
            }
            QStyleOption endOpt = *option;
            endOpt.state |= (State)State_Animating;
            t->setStartImage(startImage);
            d->animator.startAnimation(t);
            endImage.fill(0);
            QPainter endPainter(&endImage);
            drawPrimitive(element, &endOpt, &endPainter, widget);
            t->setEndImage(endImage);
            t->setDuration(130);
            t->setStartTime(QTime::currentTime());
        }
    }

    switch (element) {
    case PE_PanelLineEdit: {
        painter->save();
        if (option->state & State_Enabled)
            drawCornerImage(d->lineeditImage, painter, option->rect, 2, 2, 2, 2);
        else
            drawCornerImage(d->lineeditImage_disabled, painter, option->rect, 2, 2, 2, 2);

        if (option->state & State_HasFocus || option->state & State_MouseOver) {
            QColor hover = StyleHelper::baseColor();
            if (state & State_HasFocus)
                hover.setAlpha(100);
            else
                hover.setAlpha(50);

            painter->setPen(QPen(hover, 1));
            painter->drawRect(option->rect.adjusted(1, 1, -2 ,-2));
        }
        painter->restore();
    }
    break;

    case PE_FrameStatusBarItem:
        break;

    case PE_PanelButtonTool: {
        Animation *anim = d->animator.widgetAnimation(widget);
        if (!animating && anim) {
            anim->paint(painter, option);
        } else {
            bool pressed = option->state & State_Sunken || option->state & State_On;
            QColor shadow(0, 0, 0, 30);
            painter->setPen(shadow);
            if (pressed) {
                QColor shade(0, 0, 0, 40);
                painter->fillRect(rect, shade);
                painter->drawLine(rect.topLeft() + QPoint(1, 0), rect.topRight() - QPoint(1, 0));
                painter->drawLine(rect.topLeft(), rect.bottomLeft());
                painter->drawLine(rect.topRight(), rect.bottomRight());
                // painter->drawLine(rect.bottomLeft()  + QPoint(1, 0), rect.bottomRight()  - QPoint(1, 0));
                QColor highlight(255, 255, 255, 30);
                painter->setPen(highlight);
            } else if (option->state & State_Enabled &&
                       option->state & State_MouseOver) {
                QColor lighter(255, 255, 255, 37);
                painter->fillRect(rect, lighter);
            }
        }
    }
    break;

    case PE_PanelStatusBar: {
        painter->save();
        QLinearGradient grad(option->rect.topLeft(), QPoint(rect.center().x(), rect.bottom()));
        QColor startColor = StyleHelper::shadowColor().darker(164);
        QColor endColor = StyleHelper::baseColor().darker(130);
        grad.setColorAt(0, endColor);
        grad.setColorAt(1, endColor);
        painter->fillRect(option->rect, grad);
        painter->setPen(QColor(255, 255, 255, 60));
        painter->drawLine(rect.topLeft() + QPoint(0,1),
                          rect.topRight()+ QPoint(0,1));
        painter->setPen(StyleHelper::borderColor().darker(110));
        painter->drawLine(rect.topLeft(), rect.topRight());
        painter->restore();
    }
    break;

    case PE_IndicatorToolBarSeparator: {
        QColor separatorColor = StyleHelper::borderColor();
        separatorColor.setAlpha(100);
        painter->setPen(separatorColor);
        const int margin = 3;
        if (option->state & State_Horizontal) {
            const int offset = rect.width()/2;
            painter->drawLine(rect.bottomLeft().x() + offset,
                              rect.bottomLeft().y() - margin,
                              rect.topLeft().x() + offset,
                              rect.topLeft().y() + margin);
        } else { //Draw vertical separator
            const int offset = rect.height()/2;
            painter->setPen(QPen(option->palette.background().color().darker(110)));
            painter->drawLine(rect.topLeft().x() + margin ,
                              rect.topLeft().y() + offset,
                              rect.topRight().x() - margin,
                              rect.topRight().y() + offset);
        }
    }
    break;

    case PE_IndicatorToolBarHandle: {
        bool horizontal = option->state & State_Horizontal;
        painter->save();
        QPainterPath path;
        int x = option->rect.x() + horizontal ? 2 : 6;
        int y = option->rect.y() + horizontal ? 6 : 2;
        static const int RectHeight = 2;
        if (horizontal) {
            while (y < option->rect.height() - RectHeight - 6) {
                path.moveTo(x, y);
                path.addRect(x, y, RectHeight, RectHeight);
                y += 6;
            }
        } else {
            while (x < option->rect.width() - RectHeight - 6) {
                path.moveTo(x, y);
                path.addRect(x, y, RectHeight, RectHeight);
                x += 6;
            }
        }

        painter->setPen(Qt::NoPen);
        QColor dark = StyleHelper::borderColor();
        dark.setAlphaF(0.4);

        QColor light = StyleHelper::baseColor();
        light.setAlphaF(0.4);

        painter->fillPath(path, light);
        painter->save();
        painter->translate(1, 1);
        painter->fillPath(path, dark);
        painter->restore();
        painter->translate(3, 3);
        painter->fillPath(path, light);
        painter->translate(1, 1);
        painter->fillPath(path, dark);
        painter->restore();
    }
    break;
    case PE_IndicatorArrowUp:
    case PE_IndicatorArrowDown:
    case PE_IndicatorArrowRight:
    case PE_IndicatorArrowLeft: {
        // From windowsstyle but modified to enable AA
        if (option->rect.width() <= 1 || option->rect.height() <= 1)
            break;

        QRect r = option->rect;
        int size = qMin(r.height(), r.width());
        QPixmap pixmap;
        QString pixmapName;
        pixmapName.sprintf("%s-%s-%d-%d-%d-%lld",
                           "$qt_ia", metaObject()->className(),
                           uint(option->state), element,
                           size, option->palette.cacheKey());
        if (!QPixmapCache::find(pixmapName, pixmap)) {
            int border = size/5;
            int sqsize = 2*(size/2);
            QImage image(sqsize, sqsize, QImage::Format_ARGB32);
            image.fill(Qt::transparent);
            QPainter imagePainter(&image);
            imagePainter.setRenderHint(QPainter::Antialiasing, true);
            imagePainter.translate(0.5, 0.5);
            QPolygon a;
            switch (element) {
            case PE_IndicatorArrowUp:
                a.setPoints(3, border, sqsize/2,  sqsize/2, border,  sqsize - border, sqsize/2);
                break;
            case PE_IndicatorArrowDown:
                a.setPoints(3, border, sqsize/2,  sqsize/2, sqsize - border,  sqsize - border, sqsize/2);
                break;
            case PE_IndicatorArrowRight:
                a.setPoints(3, sqsize - border, sqsize/2,  sqsize/2, border,  sqsize/2, sqsize - border);
                break;
            case PE_IndicatorArrowLeft:
                a.setPoints(3, border, sqsize/2,  sqsize/2, border,  sqsize/2, sqsize - border);
                break;
            default:
                break;
            }

            int bsx = 0;
            int bsy = 0;

            if (option->state & State_Sunken) {
                bsx = pixelMetric(PM_ButtonShiftHorizontal);
                bsy = pixelMetric(PM_ButtonShiftVertical);
            }

            QRect bounds = a.boundingRect();
            int sx = sqsize / 2 - bounds.center().x() - 1;
            int sy = sqsize / 2 - bounds.center().y() - 1;
            imagePainter.translate(sx + bsx, sy + bsy);

            if (!(option->state & State_Enabled)) {
                QColor foreGround(150, 150, 150, 150);
                imagePainter.setBrush(option->palette.mid().color());
                imagePainter.setPen(option->palette.mid().color());
            } else {
                QColor shadow(0, 0, 0, 100);
                imagePainter.translate(0, 1);
                imagePainter.setPen(shadow);
                imagePainter.setBrush(shadow);
                QColor foreGround(255, 255, 255, 210);
                imagePainter.drawPolygon(a);
                imagePainter.translate(0, -1);
                imagePainter.setPen(foreGround);
                imagePainter.setBrush(foreGround);
            }
            imagePainter.drawPolygon(a);
            imagePainter.end();
            pixmap = QPixmap::fromImage(image);
            QPixmapCache::insert(pixmapName, pixmap);
        }
        int xOffset = r.x() + (r.width() - size)/2;
        int yOffset = r.y() + (r.height() - size)/2;
        painter->drawPixmap(xOffset, yOffset, pixmap);
    }
    break;

    default:
        d->style->drawPrimitive(element, option, painter, widget);
        break;
    }
}
Beispiel #9
0
void TransformDrawEngine::SoftwareTransformAndDraw(
    int prim, u8 *decoded, LinkedShader *program, int vertexCount, u32 vertType, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex) {

    bool throughmode = (vertType & GE_VTYPE_THROUGH_MASK) != 0;
    bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled();

    // TODO: Split up into multiple draw calls for GLES 2.0 where you can't guarantee support for more than 0x10000 verts.

#if defined(MOBILE_DEVICE)
    if (vertexCount > 0x10000/3)
        vertexCount = 0x10000/3;
#endif

    float uscale = 1.0f;
    float vscale = 1.0f;
    bool scaleUV = false;
    if (throughmode) {
        uscale /= gstate_c.curTextureWidth;
        vscale /= gstate_c.curTextureHeight;
    } else {
        scaleUV = !g_Config.bPrescaleUV;
    }

    bool skinningEnabled = vertTypeIsSkinningEnabled(vertType);

    int w = gstate.getTextureWidth(0);
    int h = gstate.getTextureHeight(0);
    float widthFactor = (float) w / (float) gstate_c.curTextureWidth;
    float heightFactor = (float) h / (float) gstate_c.curTextureHeight;

    Lighter lighter(vertType);
    float fog_end = getFloat24(gstate.fog1);
    float fog_slope = getFloat24(gstate.fog2);

    VertexReader reader(decoded, decVtxFormat, vertType);
    for (int index = 0; index < maxIndex; index++) {
        reader.Goto(index);

        float v[3] = {0, 0, 0};
        float c0[4] = {1, 1, 1, 1};
        float c1[4] = {0, 0, 0, 0};
        float uv[3] = {0, 0, 1};
        float fogCoef = 1.0f;

        if (throughmode) {
            // Do not touch the coordinates or the colors. No lighting.
            reader.ReadPos(v);
            if (reader.hasColor0()) {
                reader.ReadColor0(c0);
                for (int j = 0; j < 4; j++) {
                    c1[j] = 0.0f;
                }
            } else {
                c0[0] = gstate.getMaterialAmbientR() / 255.f;
                c0[1] = gstate.getMaterialAmbientG() / 255.f;
                c0[2] = gstate.getMaterialAmbientB() / 255.f;
                c0[3] = gstate.getMaterialAmbientA() / 255.f;
            }

            if (reader.hasUV()) {
                reader.ReadUV(uv);

                uv[0] *= uscale;
                uv[1] *= vscale;
            }
            fogCoef = 1.0f;
            // Scale UV?
        } else {
            // We do software T&L for now
            float out[3], norm[3];
            float pos[3], nrm[3];
            Vec3f normal(0, 0, 1);
            reader.ReadPos(pos);
            if (reader.hasNormal())
                reader.ReadNrm(nrm);

            if (!skinningEnabled) {
                Vec3ByMatrix43(out, pos, gstate.worldMatrix);
                if (reader.hasNormal()) {
                    Norm3ByMatrix43(norm, nrm, gstate.worldMatrix);
                    normal = Vec3f(norm).Normalized();
                }
            } else {
                float weights[8];
                reader.ReadWeights(weights);
                // Skinning
                Vec3f psum(0,0,0);
                Vec3f nsum(0,0,0);
                for (int i = 0; i < vertTypeGetNumBoneWeights(vertType); i++) {
                    if (weights[i] != 0.0f) {
                        Vec3ByMatrix43(out, pos, gstate.boneMatrix+i*12);
                        Vec3f tpos(out);
                        psum += tpos * weights[i];
                        if (reader.hasNormal()) {
                            Norm3ByMatrix43(norm, nrm, gstate.boneMatrix+i*12);
                            Vec3f tnorm(norm);
                            nsum += tnorm * weights[i];
                        }
                    }
                }

                // Yes, we really must multiply by the world matrix too.
                Vec3ByMatrix43(out, psum.AsArray(), gstate.worldMatrix);
                if (reader.hasNormal()) {
                    Norm3ByMatrix43(norm, nsum.AsArray(), gstate.worldMatrix);
                    normal = Vec3f(norm).Normalized();
                }
            }

            // Perform lighting here if enabled. don't need to check through, it's checked above.
            float unlitColor[4] = {1, 1, 1, 1};
            if (reader.hasColor0()) {
                reader.ReadColor0(unlitColor);
            } else {
                unlitColor[0] = gstate.getMaterialAmbientR() / 255.f;
                unlitColor[1] = gstate.getMaterialAmbientG() / 255.f;
                unlitColor[2] = gstate.getMaterialAmbientB() / 255.f;
                unlitColor[3] = gstate.getMaterialAmbientA() / 255.f;
            }
            float litColor0[4];
            float litColor1[4];
            lighter.Light(litColor0, litColor1, unlitColor, out, normal);

            if (gstate.isLightingEnabled()) {
                // Don't ignore gstate.lmode - we should send two colors in that case
                for (int j = 0; j < 4; j++) {
                    c0[j] = litColor0[j];
                }
                if (lmode) {
                    // Separate colors
                    for (int j = 0; j < 4; j++) {
                        c1[j] = litColor1[j];
                    }
                } else {
                    // Summed color into c0
                    for (int j = 0; j < 4; j++) {
                        c0[j] = ((c0[j] + litColor1[j]) > 1.0f) ? 1.0f : (c0[j] + litColor1[j]);
                    }
                }
            } else {
                if (reader.hasColor0()) {
                    for (int j = 0; j < 4; j++) {
                        c0[j] = unlitColor[j];
                    }
                } else {
                    c0[0] = gstate.getMaterialAmbientR() / 255.f;
                    c0[1] = gstate.getMaterialAmbientG() / 255.f;
                    c0[2] = gstate.getMaterialAmbientB() / 255.f;
                    c0[3] = gstate.getMaterialAmbientA() / 255.f;
                }
                if (lmode) {
                    for (int j = 0; j < 4; j++) {
                        c1[j] = 0.0f;
                    }
                }
            }

            float ruv[2] = {0.0f, 0.0f};
            if (reader.hasUV())
                reader.ReadUV(ruv);

            // Perform texture coordinate generation after the transform and lighting - one style of UV depends on lights.
            switch (gstate.getUVGenMode()) {
            case GE_TEXMAP_TEXTURE_COORDS:	// UV mapping
            case GE_TEXMAP_UNKNOWN: // Seen in Riviera.  Unsure of meaning, but this works.
                // Texture scale/offset is only performed in this mode.
                if (scaleUV) {
                    uv[0] = ruv[0]*gstate_c.uv.uScale + gstate_c.uv.uOff;
                    uv[1] = ruv[1]*gstate_c.uv.vScale + gstate_c.uv.vOff;
                } else {
                    uv[0] = ruv[0];
                    uv[1] = ruv[1];
                }
                uv[2] = 1.0f;
                break;

            case GE_TEXMAP_TEXTURE_MATRIX:
            {
                // Projection mapping
                Vec3f source;
                switch (gstate.getUVProjMode())	{
                case GE_PROJMAP_POSITION: // Use model space XYZ as source
                    source = pos;
                    break;

                case GE_PROJMAP_UV: // Use unscaled UV as source
                    source = Vec3f(ruv[0], ruv[1], 0.0f);
                    break;

                case GE_PROJMAP_NORMALIZED_NORMAL: // Use normalized normal as source
                    if (reader.hasNormal()) {
                        source = Vec3f(norm).Normalized();
                    } else {
                        ERROR_LOG_REPORT(G3D, "Normal projection mapping without normal?");
                        source = Vec3f(0.0f, 0.0f, 1.0f);
                    }
                    break;

                case GE_PROJMAP_NORMAL: // Use non-normalized normal as source!
                    if (reader.hasNormal()) {
                        source = Vec3f(norm);
                    } else {
                        ERROR_LOG_REPORT(G3D, "Normal projection mapping without normal?");
                        source = Vec3f(0.0f, 0.0f, 1.0f);
                    }
                    break;
                }

                float uvw[3];
                Vec3ByMatrix43(uvw, &source.x, gstate.tgenMatrix);
                uv[0] = uvw[0];
                uv[1] = uvw[1];
                uv[2] = uvw[2];
            }
            break;

            case GE_TEXMAP_ENVIRONMENT_MAP:
                // Shade mapping - use two light sources to generate U and V.
            {
                Vec3f lightpos0 = Vec3f(gstate_c.lightpos[gstate.getUVLS0()]).Normalized();
                Vec3f lightpos1 = Vec3f(gstate_c.lightpos[gstate.getUVLS1()]).Normalized();

                uv[0] = (1.0f + Dot(lightpos0, normal))/2.0f;
                uv[1] = (1.0f - Dot(lightpos1, normal))/2.0f;
                uv[2] = 1.0f;
            }
            break;

            default:
                // Illegal
                ERROR_LOG_REPORT(G3D, "Impossible UV gen mode? %d", gstate.getUVGenMode());
                break;
            }

            uv[0] = uv[0] * widthFactor;
            uv[1] = uv[1] * heightFactor;

            // Transform the coord by the view matrix.
            Vec3ByMatrix43(v, out, gstate.viewMatrix);
            fogCoef = (v[2] + fog_end) * fog_slope;
        }

        // TODO: Write to a flexible buffer, we don't always need all four components.
        memcpy(&transformed[index].x, v, 3 * sizeof(float));
        transformed[index].fog = fogCoef;
        memcpy(&transformed[index].u, uv, 3 * sizeof(float));
        if (gstate_c.flipTexture) {
            transformed[index].v = 1.0f - transformed[index].v;
        }
        for (int i = 0; i < 4; i++) {
            transformed[index].color0[i] = c0[i] * 255.0f;
        }
        for (int i = 0; i < 3; i++) {
            transformed[index].color1[i] = c1[i] * 255.0f;
        }
    }

    // Here's the best opportunity to try to detect rectangles used to clear the screen, and
    // replace them with real OpenGL clears. This can provide a speedup on certain mobile chips.
    // Disabled for now - depth does not come out exactly the same.
    //
    // An alternative option is to simply ditch all the verts except the first and last to create a single
    // rectangle out of many. Quite a small optimization though.
    if (false && maxIndex > 1 && gstate.isModeClear() && prim == GE_PRIM_RECTANGLES && IsReallyAClear(maxIndex)) {
        u32 clearColor;
        memcpy(&clearColor, transformed[0].color0, 4);
        float clearDepth = transformed[0].z;
        const float col[4] = {
            ((clearColor & 0xFF)) / 255.0f,
            ((clearColor & 0xFF00) >> 8) / 255.0f,
            ((clearColor & 0xFF0000) >> 16) / 255.0f,
            ((clearColor & 0xFF000000) >> 24) / 255.0f,
        };

        bool colorMask = gstate.isClearModeColorMask();
        bool alphaMask = gstate.isClearModeAlphaMask();
        glstate.colorMask.set(colorMask, colorMask, colorMask, alphaMask);
        if (alphaMask) {
            glstate.stencilTest.set(true);
            // Clear stencil
            // TODO: extract the stencilValue properly, see below
            int stencilValue = 0;
            glstate.stencilFunc.set(GL_ALWAYS, stencilValue, 255);
        } else {
            // Don't touch stencil
            glstate.stencilTest.set(false);
        }
        glstate.scissorTest.set(false);
        bool depthMask = gstate.isClearModeDepthMask();

        int target = 0;
        if (colorMask || alphaMask) target |= GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
        if (depthMask) target |= GL_DEPTH_BUFFER_BIT;

        glClearColor(col[0], col[1], col[2], col[3]);
#ifdef USING_GLES2
        glClearDepthf(clearDepth);
#else
        glClearDepth(clearDepth);
#endif
        glClearStencil(0);  // TODO - take from alpha?
        glClear(target);
        return;
    }
Beispiel #10
0
	hsl_colour hsl_colour::lighter(double aDelta) const
	{
		return lighter(1.0, aDelta);
	}
Beispiel #11
0
	hsl_colour hsl_colour::with_lightness(double aNewLightness) const
	{
		return lighter(0.0, aNewLightness);
	}
void SoftwareTransform(
	int prim, int vertexCount, u32 vertType, u16 *&inds, int indexType,
	const DecVtxFormat &decVtxFormat, int &maxIndex, TransformedVertex *&drawBuffer, int &numTrans, bool &drawIndexed, const SoftwareTransformParams *params, SoftwareTransformResult *result) {
	u8 *decoded = params->decoded;
	FramebufferManagerCommon *fbman = params->fbman;
	TextureCacheCommon *texCache = params->texCache;
	TransformedVertex *transformed = params->transformed;
	TransformedVertex *transformedExpanded = params->transformedExpanded;
	float ySign = 1.0f;
	bool throughmode = (vertType & GE_VTYPE_THROUGH_MASK) != 0;
	bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled();

	// TODO: Split up into multiple draw calls for GLES 2.0 where you can't guarantee support for more than 0x10000 verts.

#if defined(MOBILE_DEVICE)
	if (vertexCount > 0x10000/3)
		vertexCount = 0x10000/3;
#endif

	float uscale = 1.0f;
	float vscale = 1.0f;
	if (throughmode) {
		uscale /= gstate_c.curTextureWidth;
		vscale /= gstate_c.curTextureHeight;
	}

	bool skinningEnabled = vertTypeIsSkinningEnabled(vertType);

	const int w = gstate.getTextureWidth(0);
	const int h = gstate.getTextureHeight(0);
	float widthFactor = (float) w / (float) gstate_c.curTextureWidth;
	float heightFactor = (float) h / (float) gstate_c.curTextureHeight;

	Lighter lighter(vertType);
	float fog_end = getFloat24(gstate.fog1);
	float fog_slope = getFloat24(gstate.fog2);
	// Same fixup as in ShaderManager.cpp
	if (my_isinf(fog_slope)) {
		// not really sure what a sensible value might be.
		fog_slope = fog_slope < 0.0f ? -10000.0f : 10000.0f;
	}
	if (my_isnan(fog_slope)) {
		// Workaround for https://github.com/hrydgard/ppsspp/issues/5384#issuecomment-38365988
		// Just put the fog far away at a large finite distance.
		// Infinities and NaNs are rather unpredictable in shaders on many GPUs
		// so it's best to just make it a sane calculation.
		fog_end = 100000.0f;
		fog_slope = 1.0f;
	}

	VertexReader reader(decoded, decVtxFormat, vertType);
	if (throughmode) {
		for (int index = 0; index < maxIndex; index++) {
			// Do not touch the coordinates or the colors. No lighting.
			reader.Goto(index);
			// TODO: Write to a flexible buffer, we don't always need all four components.
			TransformedVertex &vert = transformed[index];
			reader.ReadPos(vert.pos);

			if (reader.hasColor0()) {
				reader.ReadColor0_8888(vert.color0);
			} else {
				vert.color0_32 = gstate.getMaterialAmbientRGBA();
			}

			if (reader.hasUV()) {
				reader.ReadUV(vert.uv);

				vert.u *= uscale;
				vert.v *= vscale;
			} else {
				vert.u = 0.0f;
				vert.v = 0.0f;
			}

			// Ignore color1 and fog, never used in throughmode anyway.
			// The w of uv is also never used (hardcoded to 1.0.)
		}
	} else {
		// Okay, need to actually perform the full transform.
		for (int index = 0; index < maxIndex; index++) {
			reader.Goto(index);

			float v[3] = {0, 0, 0};
			Vec4f c0 = Vec4f(1, 1, 1, 1);
			Vec4f c1 = Vec4f(0, 0, 0, 0);
			float uv[3] = {0, 0, 1};
			float fogCoef = 1.0f;

			// We do software T&L for now
			float out[3];
			float pos[3];
			Vec3f normal(0, 0, 1);
			Vec3f worldnormal(0, 0, 1);
			reader.ReadPos(pos);

			if (!skinningEnabled) {
				Vec3ByMatrix43(out, pos, gstate.worldMatrix);
				if (reader.hasNormal()) {
					reader.ReadNrm(normal.AsArray());
					if (gstate.areNormalsReversed()) {
						normal = -normal;
					}
					Norm3ByMatrix43(worldnormal.AsArray(), normal.AsArray(), gstate.worldMatrix);
					worldnormal = worldnormal.Normalized();
				}
			} else {
				float weights[8];
				reader.ReadWeights(weights);
				if (reader.hasNormal())
					reader.ReadNrm(normal.AsArray());

				// Skinning
				Vec3f psum(0, 0, 0);
				Vec3f nsum(0, 0, 0);
				for (int i = 0; i < vertTypeGetNumBoneWeights(vertType); i++) {
					if (weights[i] != 0.0f) {
						Vec3ByMatrix43(out, pos, gstate.boneMatrix+i*12);
						Vec3f tpos(out);
						psum += tpos * weights[i];
						if (reader.hasNormal()) {
							Vec3f norm;
							Norm3ByMatrix43(norm.AsArray(), normal.AsArray(), gstate.boneMatrix+i*12);
							nsum += norm * weights[i];
						}
					}
				}

				// Yes, we really must multiply by the world matrix too.
				Vec3ByMatrix43(out, psum.AsArray(), gstate.worldMatrix);
				if (reader.hasNormal()) {
					normal = nsum;
					if (gstate.areNormalsReversed()) {
						normal = -normal;
					}
					Norm3ByMatrix43(worldnormal.AsArray(), normal.AsArray(), gstate.worldMatrix);
					worldnormal = worldnormal.Normalized();
				}
			}

			// Perform lighting here if enabled. don't need to check through, it's checked above.
			Vec4f unlitColor = Vec4f(1, 1, 1, 1);
			if (reader.hasColor0()) {
				reader.ReadColor0(&unlitColor.x);
			} else {
				unlitColor = Vec4f::FromRGBA(gstate.getMaterialAmbientRGBA());
			}

			if (gstate.isLightingEnabled()) {
				float litColor0[4];
				float litColor1[4];
				lighter.Light(litColor0, litColor1, unlitColor.AsArray(), out, worldnormal);

				// Don't ignore gstate.lmode - we should send two colors in that case
				for (int j = 0; j < 4; j++) {
					c0[j] = litColor0[j];
				}
				if (lmode) {
					// Separate colors
					for (int j = 0; j < 4; j++) {
						c1[j] = litColor1[j];
					}
				} else {
					// Summed color into c0 (will clamp in ToRGBA().)
					for (int j = 0; j < 4; j++) {
						c0[j] += litColor1[j];
					}
				}
			} else {
				if (reader.hasColor0()) {
					for (int j = 0; j < 4; j++) {
						c0[j] = unlitColor[j];
					}
				} else {
					c0 = Vec4f::FromRGBA(gstate.getMaterialAmbientRGBA());
				}
				if (lmode) {
					// c1 is already 0.
				}
			}

			float ruv[2] = {0.0f, 0.0f};
			if (reader.hasUV())
				reader.ReadUV(ruv);

			// Perform texture coordinate generation after the transform and lighting - one style of UV depends on lights.
			switch (gstate.getUVGenMode()) {
			case GE_TEXMAP_TEXTURE_COORDS:	// UV mapping
			case GE_TEXMAP_UNKNOWN: // Seen in Riviera.  Unsure of meaning, but this works.
				// We always prescale in the vertex decoder now.
				uv[0] = ruv[0];
				uv[1] = ruv[1];
				uv[2] = 1.0f;
				break;

			case GE_TEXMAP_TEXTURE_MATRIX:
				{
					// Projection mapping
					Vec3f source;
					switch (gstate.getUVProjMode())	{
					case GE_PROJMAP_POSITION: // Use model space XYZ as source
						source = pos;
						break;

					case GE_PROJMAP_UV: // Use unscaled UV as source
						source = Vec3f(ruv[0], ruv[1], 0.0f);
						break;

					case GE_PROJMAP_NORMALIZED_NORMAL: // Use normalized normal as source
						source = normal.Normalized();
						if (!reader.hasNormal()) {
							ERROR_LOG_REPORT(G3D, "Normal projection mapping without normal?");
						}
						break;

					case GE_PROJMAP_NORMAL: // Use non-normalized normal as source!
						source = normal;
						if (!reader.hasNormal()) {
							ERROR_LOG_REPORT(G3D, "Normal projection mapping without normal?");
						}
						break;
					}

					float uvw[3];
					Vec3ByMatrix43(uvw, &source.x, gstate.tgenMatrix);
					uv[0] = uvw[0];
					uv[1] = uvw[1];
					uv[2] = uvw[2];
				}
				break;

			case GE_TEXMAP_ENVIRONMENT_MAP:
				// Shade mapping - use two light sources to generate U and V.
				{
					Vec3f lightpos0 = Vec3f(&lighter.lpos[gstate.getUVLS0() * 3]).Normalized();
					Vec3f lightpos1 = Vec3f(&lighter.lpos[gstate.getUVLS1() * 3]).Normalized();

					uv[0] = (1.0f + Dot(lightpos0, worldnormal))/2.0f;
					uv[1] = (1.0f + Dot(lightpos1, worldnormal))/2.0f;
					uv[2] = 1.0f;
				}
				break;

			default:
				// Illegal
				ERROR_LOG_REPORT(G3D, "Impossible UV gen mode? %d", gstate.getUVGenMode());
				break;
			}

			uv[0] = uv[0] * widthFactor;
			uv[1] = uv[1] * heightFactor;

			// Transform the coord by the view matrix.
			Vec3ByMatrix43(v, out, gstate.viewMatrix);
			fogCoef = (v[2] + fog_end) * fog_slope;

			// TODO: Write to a flexible buffer, we don't always need all four components.
			memcpy(&transformed[index].x, v, 3 * sizeof(float));
			transformed[index].fog = fogCoef;
			memcpy(&transformed[index].u, uv, 3 * sizeof(float));
			transformed[index].color0_32 = c0.ToRGBA();
			transformed[index].color1_32 = c1.ToRGBA();

			// The multiplication by the projection matrix is still performed in the vertex shader.
			// So is vertex depth rounding, to simulate the 16-bit depth buffer.
		}
	}

	// Here's the best opportunity to try to detect rectangles used to clear the screen, and
	// replace them with real clears. This can provide a speedup on certain mobile chips.
	//
	// An alternative option is to simply ditch all the verts except the first and last to create a single
	// rectangle out of many. Quite a small optimization though.
	// Experiment: Disable on PowerVR (see issue #6290)
	// TODO: This bleeds outside the play area in non-buffered mode. Big deal? Probably not.
	bool reallyAClear = false;
	if (maxIndex > 1 && prim == GE_PRIM_RECTANGLES && gstate.isModeClear()) {
		int scissorX2 = gstate.getScissorX2() + 1;
		int scissorY2 = gstate.getScissorY2() + 1;
		reallyAClear = IsReallyAClear(transformed, maxIndex, scissorX2, scissorY2);
	}
	if (reallyAClear && gl_extensions.gpuVendor != GPU_VENDOR_POWERVR) {  // && g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) {
		// If alpha is not allowed to be separate, it must match for both depth/stencil and color.  Vulkan requires this.
		bool alphaMatchesColor = gstate.isClearModeColorMask() == gstate.isClearModeAlphaMask();
		bool depthMatchesStencil = gstate.isClearModeAlphaMask() == gstate.isClearModeDepthMask();
		if (params->allowSeparateAlphaClear || (alphaMatchesColor && depthMatchesStencil)) {
			result->color = transformed[1].color0_32;
			// Need to rescale from a [0, 1] float.  This is the final transformed value.
			result->depth = ToScaledDepth((s16)(int)(transformed[1].z * 65535.0f));
			result->action = SW_CLEAR;
			return;
		}
	}

	// This means we're using a framebuffer (and one that isn't big enough.)
	if (gstate_c.curTextureHeight < (u32)h && maxIndex >= 2) {
		// Even if not rectangles, this will detect if either of the first two are outside the framebuffer.
		// HACK: Adding one pixel margin to this detection fixes issues in Assassin's Creed : Bloodlines,
		// while still keeping BOF working (see below).
		const float invTexH = 1.0f / gstate_c.curTextureHeight; // size of one texel.
		bool tlOutside;
		bool tlAlmostOutside;
		bool brOutside;
		// If we're outside heightFactor, then v must be wrapping or clamping.  Avoid this workaround.
		// If we're <= 1.0f, we're inside the framebuffer (workaround not needed.)
		// We buffer that 1.0f a little more with a texel to avoid some false positives.
		tlOutside = transformed[0].v <= heightFactor && transformed[0].v > 1.0f + invTexH;
		brOutside = transformed[1].v <= heightFactor && transformed[1].v > 1.0f + invTexH;
		// Careful: if br is outside, but tl is well inside, this workaround still doesn't make sense.
		// We go with halfway, since we overestimate framebuffer heights sometimes but not by much.
		tlAlmostOutside = transformed[0].v <= heightFactor && transformed[0].v >= 0.5f;
		if (tlOutside || (brOutside && tlAlmostOutside)) {
			// Okay, so we're texturing from outside the framebuffer, but inside the texture height.
			// Breath of Fire 3 does this to access a render surface at an offset.
			const u32 bpp = fbman->GetTargetFormat() == GE_FORMAT_8888 ? 4 : 2;
			const u32 prevH = texCache->AttachedDrawingHeight();
			const u32 fb_size = bpp * fbman->GetTargetStride() * prevH;
			const u32 prevYOffset = gstate_c.curTextureYOffset;
			if (texCache->SetOffsetTexture(fb_size)) {
				const float oldWidthFactor = widthFactor;
				const float oldHeightFactor = heightFactor;
				widthFactor = (float) w / (float) gstate_c.curTextureWidth;
				heightFactor = (float) h / (float) gstate_c.curTextureHeight;

				// We've already baked in the old gstate_c.curTextureYOffset, so correct.
				const float yDiff = (float) (prevH + prevYOffset - gstate_c.curTextureYOffset) / (float) h;
				for (int index = 0; index < maxIndex; ++index) {
					transformed[index].u *= widthFactor / oldWidthFactor;
					// Inverse it back to scale to the new FBO, and add 1.0f to account for old FBO.
					transformed[index].v = (transformed[index].v / oldHeightFactor - yDiff) * heightFactor;
				}
			}
		}
	}

	// Step 2: expand rectangles.
	drawBuffer = transformed;
	numTrans = 0;
	drawIndexed = false;

	if (prim != GE_PRIM_RECTANGLES) {
		// We can simply draw the unexpanded buffer.
		numTrans = vertexCount;
		drawIndexed = true;
	} else {
		bool useBufferedRendering = g_Config.iRenderingMode != FB_NON_BUFFERED_MODE;
		if (useBufferedRendering)
			ySign = -ySign;

		float flippedMatrix[16];
		if (!throughmode) {
			memcpy(&flippedMatrix, gstate.projMatrix, 16 * sizeof(float));

			const bool invertedY = useBufferedRendering ? (gstate_c.vpHeight < 0) : (gstate_c.vpHeight > 0);
			if (invertedY) {
				flippedMatrix[1] = -flippedMatrix[1];
				flippedMatrix[5] = -flippedMatrix[5];
				flippedMatrix[9] = -flippedMatrix[9];
				flippedMatrix[13] = -flippedMatrix[13];
			}
			const bool invertedX = gstate_c.vpWidth < 0;
			if (invertedX) {
				flippedMatrix[0] = -flippedMatrix[0];
				flippedMatrix[4] = -flippedMatrix[4];
				flippedMatrix[8] = -flippedMatrix[8];
				flippedMatrix[12] = -flippedMatrix[12];
			}
		}

		//rectangles always need 2 vertices, disregard the last one if there's an odd number
		vertexCount = vertexCount & ~1;
		numTrans = 0;
		drawBuffer = transformedExpanded;
		TransformedVertex *trans = &transformedExpanded[0];
		const u16 *indsIn = (const u16 *)inds;
		u16 *newInds = inds + vertexCount;
		u16 *indsOut = newInds;
		maxIndex = 4 * vertexCount;
		for (int i = 0; i < vertexCount; i += 2) {
			const TransformedVertex &transVtxTL = transformed[indsIn[i + 0]];
			const TransformedVertex &transVtxBR = transformed[indsIn[i + 1]];

			// We have to turn the rectangle into two triangles, so 6 points.
			// This is 4 verts + 6 indices.

			// bottom right
			trans[0] = transVtxBR;

			// top right
			trans[1] = transVtxBR;
			trans[1].y = transVtxTL.y;
			trans[1].v = transVtxTL.v;

			// top left
			trans[2] = transVtxBR;
			trans[2].x = transVtxTL.x;
			trans[2].y = transVtxTL.y;
			trans[2].u = transVtxTL.u;
			trans[2].v = transVtxTL.v;

			// bottom left
			trans[3] = transVtxBR;
			trans[3].x = transVtxTL.x;
			trans[3].u = transVtxTL.u;

			// That's the four corners. Now process UV rotation.
			if (throughmode)
				RotateUVThrough(trans);
			else
				RotateUV(trans, flippedMatrix, ySign);

			// Triangle: BR-TR-TL
			indsOut[0] = i * 2 + 0;
			indsOut[1] = i * 2 + 1;
			indsOut[2] = i * 2 + 2;
			// Triangle: BL-BR-TL
			indsOut[3] = i * 2 + 3;
			indsOut[4] = i * 2 + 0;
			indsOut[5] = i * 2 + 2;
			trans += 4;
			indsOut += 6;

			numTrans += 6;
		}
		inds = newInds;
		drawIndexed = true;

		// We don't know the color until here, so we have to do it now, instead of in StateMapping.
		// Might want to reconsider the order of things later...
		if (gstate.isModeClear() && gstate.isClearModeAlphaMask()) {
			result->setStencil = true;
			if (vertexCount > 1) {
				// Take the bottom right alpha value of the first rect as the stencil value.
				// Technically, each rect could individually fill its stencil, but most of the
				// time they use the same one.
				result->stencilValue = transformed[indsIn[1]].color0[3];
			} else {
				result->stencilValue = 0;
			}
		}
	}

	result->action = SW_DRAW_PRIMITIVES;
}
Beispiel #13
0
void ManhattanStyle::drawControl(ControlElement element, const QStyleOption *option,
                                 QPainter *painter, const QWidget *widget) const
{
    if (!panelWidget(widget))
        return QProxyStyle::drawControl(element, option, painter, widget);

    switch (element) {
    case CE_Splitter:
        painter->fillRect(option->rect, Utils::StyleHelper::borderColor());
        break;

    case CE_TabBarTabShape:
        // Most styles draw a single dark outline. This looks rather ugly when combined with our
        // single pixel dark separator so we adjust the first tab to compensate for this

        if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(option)) {
            QStyleOptionTabV3 adjustedTab = *tab;
            if (tab->cornerWidgets == QStyleOptionTab::NoCornerWidgets && (
                    tab->position == QStyleOptionTab::Beginning ||
                    tab->position == QStyleOptionTab::OnlyOneTab))
            {
                if (option->direction == Qt::LeftToRight)
                    adjustedTab.rect = adjustedTab.rect.adjusted(-1, 0, 0, 0);
                else
                    adjustedTab.rect = adjustedTab.rect.adjusted(0, 0, 1 ,0);
            }
            QProxyStyle::drawControl(element, &adjustedTab, painter, widget);
            return;
        }
        break;

    case CE_MenuBarItem:
        painter->save();
        if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
            QColor highlightOutline = Utils::StyleHelper::borderColor().lighter(120);
            bool act = mbi->state & State_Selected && mbi->state & State_Sunken;
            bool dis = !(mbi->state & State_Enabled);
            Utils::StyleHelper::menuGradient(painter, option->rect, option->rect);
            QStyleOptionMenuItem item = *mbi;
            item.rect = mbi->rect;
            QPalette pal = mbi->palette;
            pal.setBrush(QPalette::ButtonText, dis ? Qt::gray : Qt::black);
            item.palette = pal;
            QCommonStyle::drawControl(element, &item, painter, widget);
            QRect r = option->rect;

            if (act) {
                // Fill|
                QColor baseColor = Utils::StyleHelper::baseColor();
                QLinearGradient grad(option->rect.topLeft(), option->rect.bottomLeft());
                grad.setColorAt(0, baseColor.lighter(120));
                grad.setColorAt(1, baseColor.lighter(130));
                painter->fillRect(option->rect.adjusted(1, 1, -1, 0), grad);

                // Outline
                painter->setPen(QPen(highlightOutline, 0));
                painter->drawLine(QPoint(r.left(), r.top() + 1), QPoint(r.left(), r.bottom()));
                painter->drawLine(QPoint(r.right(), r.top() + 1), QPoint(r.right(), r.bottom()));
                painter->drawLine(QPoint(r.left() + 1, r.top()), QPoint(r.right() - 1, r.top()));
                highlightOutline.setAlpha(60);
                painter->setPen(QPen(highlightOutline, 0));
                painter->drawPoint(r.topLeft());
                painter->drawPoint(r.topRight());

                QPalette pal = mbi->palette;
                uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
                if (!styleHint(SH_UnderlineShortcut, mbi, widget))
                    alignment |= Qt::TextHideMnemonic;
                pal.setBrush(QPalette::Text, dis ? Qt::gray : QColor(0, 0, 0, 60));
                drawItemText(painter, item.rect.translated(0, 1), alignment, pal, mbi->state & State_Enabled, mbi->text, QPalette::Text);
                pal.setBrush(QPalette::Text, dis ? Qt::gray : Qt::white);
                drawItemText(painter, item.rect, alignment, pal, mbi->state & State_Enabled, mbi->text, QPalette::Text);
            }
        }
        painter->restore();
        break;

    case CE_ComboBoxLabel:
        if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
            if (panelWidget(widget)) {
                painter->save();
                QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
                QPalette customPal = cb->palette;

                if (!cb->currentIcon.isNull()) {
                    QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal
                                                                 : QIcon::Disabled;
                    QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode);
                    QRect iconRect(editRect);
                    iconRect.setWidth(cb->iconSize.width() + 4);
                    iconRect = alignedRect(cb->direction,
                                           Qt::AlignLeft | Qt::AlignVCenter,
                                           iconRect.size(), editRect);
                    if (cb->editable)
                        painter->fillRect(iconRect, customPal.brush(QPalette::Base));
                    drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);

                    if (cb->direction == Qt::RightToLeft)
                        editRect.translate(-4 - cb->iconSize.width(), 0);
                    else
                        editRect.translate(cb->iconSize.width() + 4, 0);

                    // Reserve some space for the down-arrow
                    editRect.adjust(0, 0, -13, 0);
                }

                QString text = option->fontMetrics.elidedText(cb->currentText, Qt::ElideRight, editRect.width());
                if ((option->state & State_Enabled)) {
                    painter->setPen(QColor(0, 0, 0, 70));
                    painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text);
                } else {
                    painter->setOpacity(0.8);
                }
                painter->setPen(Utils::StyleHelper::panelTextColor());
                painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text);

                painter->restore();
            } else {
                QProxyStyle::drawControl(element, option, painter, widget);
            }
        }
        break;

    case CE_SizeGrip: {
            painter->save();
            QColor dark = Qt::white;
            dark.setAlphaF(0.1);
            int x, y, w, h;
            option->rect.getRect(&x, &y, &w, &h);
            int sw = qMin(h, w);
            if (h > w)
                painter->translate(0, h - w);
            else
                painter->translate(w - h, 0);
            int sx = x;
            int sy = y;
            int s = 4;
            painter->setPen(dark);
            if (option->direction == Qt::RightToLeft) {
                sx = x + sw;
                for (int i = 0; i < 4; ++i) {
                    painter->drawLine(x, sy, sx, sw);
                    sx -= s;
                    sy += s;
                }
            } else {
                for (int i = 0; i < 4; ++i) {
                    painter->drawLine(sx, sw, sw, sy);
                    sx += s;
                    sy += s;
                }
            }
            painter->restore();
        }
        break;

    case CE_MenuBarEmptyArea: {
            Utils::StyleHelper::menuGradient(painter, option->rect, option->rect);
            painter->save();
            painter->setPen(Utils::StyleHelper::borderColor());
            painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
            painter->restore();
        }
        break;

    case CE_ToolBar:
        {
            QRect rect = option->rect;
            bool horizontal = option->state & State_Horizontal;
            rect = option->rect;

            // Map offset for global window gradient
            QPoint offset = widget->window()->mapToGlobal(option->rect.topLeft()) -
                            widget->mapToGlobal(option->rect.topLeft());
            QRect gradientSpan;
            if (widget)
                gradientSpan = QRect(offset, widget->window()->size());

            bool drawLightColored = lightColored(widget);
            if (horizontal)
                Utils::StyleHelper::horizontalGradient(painter, gradientSpan, rect, drawLightColored);
            else
                Utils::StyleHelper::verticalGradient(painter, gradientSpan, rect, drawLightColored);

            if (!drawLightColored)
                painter->setPen(Utils::StyleHelper::borderColor());
            else
                painter->setPen(QColor(0x888888));

            if (horizontal) {
                // Note: This is a hack to determine if the
                // toolbar should draw the top or bottom outline
                // (needed for the find toolbar for instance)
                QColor lighter(Utils::StyleHelper::sidebarHighlight());
                if (drawLightColored)
                    lighter = QColor(255, 255, 255, 180);
                if (widget && widget->property("topBorder").toBool()) {
                    painter->drawLine(rect.topLeft(), rect.topRight());
                    painter->setPen(lighter);
                    painter->drawLine(rect.topLeft() + QPoint(0, 1), rect.topRight() + QPoint(0, 1));
                } else {
                    painter->drawLine(rect.bottomLeft(), rect.bottomRight());
                    painter->setPen(lighter);
                    painter->drawLine(rect.topLeft(), rect.topRight());
                }
            } else {
                painter->drawLine(rect.topLeft(), rect.bottomLeft());
                painter->drawLine(rect.topRight(), rect.bottomRight());
            }
        }
        break;

    default:
        QProxyStyle::drawControl(element, option, painter, widget);
        break;
    }
}
Beispiel #14
0
void ManhattanStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
                                   QPainter *painter, const QWidget *widget) const
{
    if (!panelWidget(widget))
        return QProxyStyle::drawPrimitive(element, option, painter, widget);

    bool animating = (option->state & State_Animating);
    int state = option->state;
    QRect rect = option->rect;
    QRect oldRect;
    QRect newRect;
    if (widget && (element == PE_PanelButtonTool) && !animating) {
        QWidget *w = const_cast<QWidget *> (widget);
        int oldState = w->property("_q_stylestate").toInt();
        oldRect = w->property("_q_stylerect").toRect();
        newRect = w->rect();
        w->setProperty("_q_stylestate", (int)option->state);
        w->setProperty("_q_stylerect", w->rect());

        // Determine the animated transition
        bool doTransition = ((state & State_On)         != (oldState & State_On)     ||
                             (state & State_MouseOver)  != (oldState & State_MouseOver));
        if (oldRect != newRect)
        {
            doTransition = false;
            d->animator.stopAnimation(widget);
        }

        if (doTransition) {
            QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
            QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
            Animation *anim = d->animator.widgetAnimation(widget);
            QStyleOption opt = *option;
            opt.state = (QStyle::State)oldState;
            opt.state |= (State)State_Animating;
            startImage.fill(0);
            Transition *t = new Transition;
            t->setWidget(w);
            QPainter startPainter(&startImage);
            if (!anim) {
                drawPrimitive(element, &opt, &startPainter, widget);
            } else {
                anim->paint(&startPainter, &opt);
                d->animator.stopAnimation(widget);
            }
            QStyleOption endOpt = *option;
            endOpt.state |= (State)State_Animating;
            t->setStartImage(startImage);
            d->animator.startAnimation(t);
            endImage.fill(0);
            QPainter endPainter(&endImage);
            drawPrimitive(element, &endOpt, &endPainter, widget);
            t->setEndImage(endImage);
            if (oldState & State_MouseOver)
                t->setDuration(150);
            else
                t->setDuration(75);
            t->setStartTime(QTime::currentTime());
        }
    }

    switch (element) {
    case PE_IndicatorDockWidgetResizeHandle:
        painter->fillRect(option->rect, Utils::StyleHelper::borderColor());
        break;
    case PE_FrameDockWidget:
        QCommonStyle::drawPrimitive(element, option, painter, widget);
        break;
    case PE_PanelLineEdit:
        {
            painter->save();

            // Fill the line edit background
            QRect filledRect = option->rect.adjusted(1, 1, -1, -1);
            painter->setBrushOrigin(filledRect.topLeft());
            painter->fillRect(filledRect, option->palette.base());

            if (option->state & State_Enabled)
                Utils::StyleHelper::drawCornerImage(d->lineeditImage, painter, option->rect, 5, 5, 5, 5);
            else
                Utils::StyleHelper::drawCornerImage(d->lineeditImage_disabled, painter, option->rect, 5, 5, 5, 5);

            if (option->state & State_HasFocus || option->state & State_MouseOver) {
                QColor hover = Utils::StyleHelper::baseColor();
                if (state & State_HasFocus)
                    hover.setAlpha(100);
                else
                    hover.setAlpha(50);

                painter->setPen(QPen(hover, 1));
                painter->drawRect(option->rect.adjusted(1, 1, -2 ,-2));
            }
            painter->restore();
        }
        break;

    case PE_FrameStatusBarItem:
        break;

    case PE_PanelButtonTool: {
            Animation *anim = d->animator.widgetAnimation(widget);
            if (!animating && anim) {
                anim->paint(painter, option);
            } else {
                bool pressed = option->state & State_Sunken || option->state & State_On;
                QColor shadow(0, 0, 0, 30);
                painter->setPen(shadow);
                if (pressed) {
                    QColor shade(0, 0, 0, 40);
                    painter->fillRect(rect, shade);
                    painter->drawLine(rect.topLeft() + QPoint(1, 0), rect.topRight() - QPoint(1, 0));
                    painter->drawLine(rect.topLeft(), rect.bottomLeft());
                    painter->drawLine(rect.topRight(), rect.bottomRight());
                   // painter->drawLine(rect.bottomLeft()  + QPoint(1, 0), rect.bottomRight()  - QPoint(1, 0));
                    QColor highlight(255, 255, 255, 30);
                    painter->setPen(highlight);
                }
                else if (option->state & State_Enabled &&
                         option->state & State_MouseOver) {
                    QColor lighter(255, 255, 255, 37);
                    painter->fillRect(rect, lighter);
                }
                if (option->state & State_HasFocus && (option->state & State_KeyboardFocusChange)) {
                    QColor highlight = option->palette.highlight().color();
                    highlight.setAlphaF(0.4);
                    painter->setPen(QPen(highlight.lighter(), 1));
                    highlight.setAlphaF(0.3);
                    painter->setBrush(highlight);
                    painter->setRenderHint(QPainter::Antialiasing);
                    QRectF rect = option->rect;
                    rect.translate(0.5, 0.5);
                    painter->drawRoundedRect(rect.adjusted(2, 2, -3, -3), 2, 2);
                }
           }
        }
        break;

    case PE_PanelStatusBar:
        {
            painter->save();
            QLinearGradient grad(option->rect.topLeft(), QPoint(rect.center().x(), rect.bottom()));
            QColor startColor = Utils::StyleHelper::shadowColor().darker(164);
            QColor endColor = Utils::StyleHelper::baseColor().darker(130);
            grad.setColorAt(0, startColor);
            grad.setColorAt(1, endColor);
            painter->fillRect(option->rect, grad);
            painter->setPen(QColor(255, 255, 255, 60));
            painter->drawLine(rect.topLeft() + QPoint(0,1),
                              rect.topRight()+ QPoint(0,1));
            painter->setPen(Utils::StyleHelper::borderColor().darker(110));
            painter->drawLine(rect.topLeft(), rect.topRight());
            painter->restore();
        }
        break;

    case PE_IndicatorToolBarSeparator:
        {
            QColor separatorColor = Utils::StyleHelper::borderColor();
            separatorColor.setAlpha(100);
            painter->setPen(separatorColor);
            const int margin = 6;
            if (option->state & State_Horizontal) {
                const int offset = rect.width()/2;
                painter->drawLine(rect.bottomLeft().x() + offset,
                            rect.bottomLeft().y() - margin,
                            rect.topLeft().x() + offset,
                            rect.topLeft().y() + margin);
            } else { //Draw vertical separator
                const int offset = rect.height()/2;
                painter->setPen(QPen(option->palette.background().color().darker(110)));
                painter->drawLine(rect.topLeft().x() + margin ,
                            rect.topLeft().y() + offset,
                            rect.topRight().x() - margin,
                            rect.topRight().y() + offset);
            }
        }
        break;

    case PE_IndicatorToolBarHandle:
        {
            bool horizontal = option->state & State_Horizontal;
            painter->save();
            QPainterPath path;
            int x = option->rect.x() + (horizontal ? 2 : 6);
            int y = option->rect.y() + (horizontal ? 6 : 2);
            static const int RectHeight = 2;
            if (horizontal) {
                while (y < option->rect.height() - RectHeight - 6) {
                    path.moveTo(x, y);
                    path.addRect(x, y, RectHeight, RectHeight);
                    y += 6;
                }
            } else {
                while (x < option->rect.width() - RectHeight - 6) {
                    path.moveTo(x, y);
                    path.addRect(x, y, RectHeight, RectHeight);
                    x += 6;
                }
            }

            painter->setPen(Qt::NoPen);
            QColor dark = Utils::StyleHelper::borderColor();
            dark.setAlphaF(0.4);

            QColor light = Utils::StyleHelper::baseColor();
            light.setAlphaF(0.4);

            painter->fillPath(path, light);
            painter->save();
            painter->translate(1, 1);
            painter->fillPath(path, dark);
            painter->restore();
            painter->translate(3, 3);
            painter->fillPath(path, light);
            painter->translate(1, 1);
            painter->fillPath(path, dark);
            painter->restore();
        }
        break;
    case PE_IndicatorArrowUp:
    case PE_IndicatorArrowDown:
    case PE_IndicatorArrowRight:
    case PE_IndicatorArrowLeft:
        {
            Utils::StyleHelper::drawArrow(element, painter, option);
        }
        break;

    default:
        QProxyStyle::drawPrimitive(element, option, painter, widget);
        break;
    }
}
Beispiel #15
0
void ManhattanStyle::drawControl(ControlElement element, const QStyleOption *option,
                                 QPainter *painter, const QWidget *widget) const
{
    if (!panelWidget(widget))
        return QProxyStyle::drawControl(element, option, painter, widget);

    switch (element) {
    case CE_Splitter:
        painter->fillRect(option->rect, StyleHelper::borderColor());
        break;

    case CE_TabBarTabShape:
        // Most styles draw a single dark outline. This looks rather ugly when combined with our
        // single pixel dark separator so we adjust the first tab to compensate for this

        if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(option)) {
            QStyleOptionTabV3 adjustedTab = *tab;
            if (tab->cornerWidgets == QStyleOptionTab::NoCornerWidgets && (
                    tab->position == QStyleOptionTab::Beginning ||
                    tab->position == QStyleOptionTab::OnlyOneTab))
            {
                if (option->direction == Qt::LeftToRight)
                    adjustedTab.rect = adjustedTab.rect.adjusted(-1, 0, 0, 0);
                else
                    adjustedTab.rect = adjustedTab.rect.adjusted(0, 0, 1 ,0);
            }
            QProxyStyle::drawControl(element, &adjustedTab, painter, widget);
            return;
        }
        break;

    case CE_MenuBarItem:
        painter->save();
        if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
            QColor highlightOutline = StyleHelper::borderColor().lighter(120);
            bool act = mbi->state & State_Sunken;
            bool dis = !(mbi->state & State_Enabled);
            StyleHelper::menuGradient(painter, option->rect, option->rect);
            QStyleOptionMenuItem item = *mbi;
            item.rect = mbi->rect;
            QPalette pal = mbi->palette;
            pal.setBrush(QPalette::ButtonText, dis ? Qt::gray : Qt::black);
            item.palette = pal;
            QCommonStyle::drawControl(element, &item, painter, widget);
            QRect r = option->rect;

            if (act) {
                // Fill|
                QColor baseColor = StyleHelper::baseColor();
                QLinearGradient grad(option->rect.topLeft(), option->rect.bottomLeft());
                grad.setColorAt(0, baseColor.lighter(120));
                grad.setColorAt(1, baseColor.lighter(130));
                painter->fillRect(option->rect.adjusted(1, 1, -1, 0), grad);

                // Outline
                painter->setPen(QPen(highlightOutline, 0));
                painter->drawLine(QPoint(r.left(), r.top() + 1), QPoint(r.left(), r.bottom()));
                painter->drawLine(QPoint(r.right(), r.top() + 1), QPoint(r.right(), r.bottom()));
                painter->drawLine(QPoint(r.left() + 1, r.top()), QPoint(r.right() - 1, r.top()));
                highlightOutline.setAlpha(60);
                painter->setPen(QPen(highlightOutline, 0));
                painter->drawPoint(r.topLeft());
                painter->drawPoint(r.topRight());

                QPalette pal = mbi->palette;
                uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
                if (!styleHint(SH_UnderlineShortcut, mbi, widget))
                    alignment |= Qt::TextHideMnemonic;
                pal.setBrush(QPalette::Text, dis ? Qt::gray : QColor(0, 0, 0, 60));
                drawItemText(painter, item.rect.translated(0, 1), alignment, pal, mbi->state & State_Enabled, mbi->text, QPalette::Text);
                pal.setBrush(QPalette::Text, dis ? Qt::gray : Qt::white);
                drawItemText(painter, item.rect, alignment, pal, mbi->state & State_Enabled, mbi->text, QPalette::Text);
            }
        }
        painter->restore();
        break;

    case CE_ComboBoxLabel:
        if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
            if (panelWidget(widget)) {
                painter->save();
                QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
                QPalette customPal = cb->palette;
                bool drawIcon = !(widget && widget->property("hideicon").toBool());

                if (!cb->currentIcon.isNull() && drawIcon) {
                    QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal
                                                                 : QIcon::Disabled;
                    QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode);
                    QRect iconRect(editRect);
                    iconRect.setWidth(cb->iconSize.width() + 4);
                    iconRect = alignedRect(cb->direction,
                                           Qt::AlignLeft | Qt::AlignVCenter,
                                           iconRect.size(), editRect);
                    if (cb->editable)
                        painter->fillRect(iconRect, customPal.brush(QPalette::Base));
                    drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);

                    if (cb->direction == Qt::RightToLeft)
                        editRect.translate(-4 - cb->iconSize.width(), 0);
                    else
                        editRect.translate(cb->iconSize.width() + 4, 0);

                    // Reserve some space for the down-arrow
                    editRect.adjust(0, 0, -13, 0);
                }

                QLatin1Char asterisk('*');
                int elideWidth = editRect.width();

                bool notElideAsterisk = widget && widget->property("notelideasterisk").toBool()
                                        && cb->currentText.endsWith(asterisk)
                                        && option->fontMetrics.width(cb->currentText) > elideWidth;

                QString text;
                if (notElideAsterisk) {
                    elideWidth -= option->fontMetrics.width(asterisk);
                    text = asterisk;
                }
                text.prepend(option->fontMetrics.elidedText(cb->currentText, Qt::ElideRight, elideWidth));

                if ((option->state & State_Enabled)) {
                    painter->setPen(QColor(0, 0, 0, 70));
                    painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text);
                } else {
                    painter->setOpacity(0.8);
                }
                painter->setPen(StyleHelper::panelTextColor());
                painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text);

                painter->restore();
            } else {
                QProxyStyle::drawControl(element, option, painter, widget);
            }
        }
        break;

    case CE_SizeGrip: {
            painter->save();
            QColor dark = Qt::white;
            dark.setAlphaF(0.1);
            int x, y, w, h;
            option->rect.getRect(&x, &y, &w, &h);
            int sw = qMin(h, w);
            if (h > w)
                painter->translate(0, h - w);
            else
                painter->translate(w - h, 0);
            int sx = x;
            int sy = y;
            int s = 4;
            painter->setPen(dark);
            if (option->direction == Qt::RightToLeft) {
                sx = x + sw;
                for (int i = 0; i < 4; ++i) {
                    painter->drawLine(x, sy, sx, sw);
                    sx -= s;
                    sy += s;
                }
            } else {
                for (int i = 0; i < 4; ++i) {
                    painter->drawLine(sx, sw, sw, sy);
                    sx += s;
                    sy += s;
                }
            }
            painter->restore();
        }
        break;

    case CE_MenuBarEmptyArea: {
            StyleHelper::menuGradient(painter, option->rect, option->rect);
            painter->save();
            painter->setPen(StyleHelper::borderColor());
            painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
            painter->restore();
        }
        break;

    case CE_ToolBar:
        {
            QRect rect = option->rect;
            bool horizontal = option->state & State_Horizontal;
            rect = option->rect;

            // Map offset for global window gradient
            QPoint offset = widget->window()->mapToGlobal(option->rect.topLeft()) -
                            widget->mapToGlobal(option->rect.topLeft());
            QRect gradientSpan;
            if (widget)
                gradientSpan = QRect(offset, widget->window()->size());

            bool drawLightColored = lightColored(widget);
            if (horizontal)
                StyleHelper::horizontalGradient(painter, gradientSpan, rect, drawLightColored);
            else
                StyleHelper::verticalGradient(painter, gradientSpan, rect, drawLightColored);

            if (!drawLightColored)
                painter->setPen(StyleHelper::borderColor());
            else
                painter->setPen(QColor(0x888888));

            if (horizontal) {
                // Note: This is a hack to determine if the
                // toolbar should draw the top or bottom outline
                // (needed for the find toolbar for instance)
                QColor lighter(StyleHelper::sidebarHighlight());
                if (drawLightColored)
                    lighter = QColor(255, 255, 255, 180);
                if (widget && widget->property("topBorder").toBool()) {
                    painter->drawLine(rect.topLeft(), rect.topRight());
                    painter->setPen(lighter);
                    painter->drawLine(rect.topLeft() + QPoint(0, 1), rect.topRight() + QPoint(0, 1));
                } else {
                    painter->drawLine(rect.bottomLeft(), rect.bottomRight());
                    painter->setPen(lighter);
                    painter->drawLine(rect.topLeft(), rect.topRight());
                }
            } else {
                painter->drawLine(rect.topLeft(), rect.bottomLeft());
                painter->drawLine(rect.topRight(), rect.bottomRight());
            }
        }
        break;

#if defined(Q_OS_MAC)
    case CE_ToolButtonLabel:
        if (const QStyleOptionToolButton *tb = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
            QStyleOptionToolButton myTb = *tb;
            myTb.state &= ~State_AutoRaise;

            QRect cr = tb->rect;
            bool needText = false;
            int alignment = 0;
            bool down = tb->state & (State_Sunken | State_On);
            // The down state is special for QToolButtons in a toolbar on the Mac
            // The text is a bit bolder and gets a drop shadow and the icons are also darkened.
            // This doesn't really fit into any particular case in QIcon, so we
            // do the majority of the work ourselves.
            if (!(tb->features & QStyleOptionToolButton::Arrow)) {
                Qt::ToolButtonStyle tbstyle = tb->toolButtonStyle;
                if (tb->icon.isNull() && !tb->text.isEmpty())
                    tbstyle = Qt::ToolButtonTextOnly;

                switch (tbstyle) {
                case Qt::ToolButtonTextOnly: {
                    needText = true;
                    alignment = Qt::AlignCenter;
                    break; }
                case Qt::ToolButtonIconOnly:
                case Qt::ToolButtonTextBesideIcon:
                case Qt::ToolButtonTextUnderIcon: {
                    QRect pr = cr;
                    QIcon::Mode iconMode = (tb->state & State_Enabled) ? QIcon::Normal
                                                                       : QIcon::Disabled;
                    QIcon::State iconState = (tb->state & State_On) ? QIcon::On
                                                                    : QIcon::Off;
                    QPixmap pixmap = tb->icon.pixmap(tb->rect.size().boundedTo(tb->iconSize), iconMode, iconState);

                    // Draw the text if it's needed.
                    if (tb->toolButtonStyle != Qt::ToolButtonIconOnly) {
                        needText = true;
                        if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
                            QMainWindow *mw = widget ? qobject_cast<QMainWindow *>(widget->window()) : 0;
                            if (mw && mw->unifiedTitleAndToolBarOnMac()) {
                                pr.setHeight(pixmap.size().height() / pixmap.devicePixelRatio());
                                cr.adjust(0, pr.bottom() + 1, 0, 1);
                            } else {
                                pr.setHeight(pixmap.size().height() / pixmap.devicePixelRatio() + 6);
                                cr.adjust(0, pr.bottom(), 0, -3);
                            }
                            alignment |= Qt::AlignCenter;
                        } else {
                            pr.setWidth(pixmap.width() / pixmap.devicePixelRatio() + 8);
                            cr.adjust(pr.right(), 0, 0, 0);
                            alignment |= Qt::AlignLeft | Qt::AlignVCenter;
                        }
                    }

                    proxy()->drawItemPixmap(painter, pr, Qt::AlignCenter, pixmap);
                    break; }
                default:
                    Q_ASSERT(false);
                    break;
                }

                if (needText) {
                    QPalette pal = tb->palette;
                    QPalette::ColorRole role = QPalette::WindowText;
                    if (!proxy()->styleHint(SH_UnderlineShortcut, tb, widget))
                        alignment |= Qt::TextHideMnemonic;
                    if (tbstyle == Qt::ToolButtonTextOnly || (tbstyle != Qt::ToolButtonTextOnly && !down)) {
                        painter->drawText(cr, alignment, tb->text);
                        if (down && tbstyle == Qt::ToolButtonTextOnly) {
                            pal = QApplication::palette("QMenu");
                            pal.setCurrentColorGroup(tb->palette.currentColorGroup());
                            role = QPalette::HighlightedText;
                        }
                    }
                    proxy()->drawItemText(painter, cr, alignment, pal,
                                          tb->state & State_Enabled, tb->text, role);
                }
            } else {
                QProxyStyle::drawControl(element, option, painter, widget);
            }
        }
        break;
#endif

    default:
        QProxyStyle::drawControl(element, option, painter, widget);
        break;
    }
}