Ejemplo n.º 1
0
qreal KDChart::TextLayoutItem::fitFontSizeToGeometry() const
{
    QFont f = realFont();
    const qreal origResult = f.pointSizeF();
    qreal result = origResult;
    const qreal minSize = mAttributes.minimalFontSize().value();
    const QSize mySize = geometry().size();
    if( mySize.isNull() )
        return result;

    const QString t = text();
    QFontMetrics fm( f );
    while( true )
    {
        const QSizeF textSize = rotatedRect( fm.boundingRect( t ), mAttributes.rotation() ).normalized().size();

        if( textSize.height() <= mySize.height() && textSize.width() <= mySize.width() )
            return result;

        result -= 0.5;
        if ( minSize > 0 && result < minSize )
            return result += 0.5;
        if( result <= 0.0 )
            return origResult;
        f.setPointSizeF( result );
        fm = QFontMetrics( f );
    }
}
Ejemplo n.º 2
0
void KDChart::TextLayoutItem::paint( QPainter* painter )
{
    // make sure, cached font is updated, if needed:
    // sizeHint();

    if( !mRect.isValid() )
        return;

    const PainterSaver painterSaver( painter );
    QFont f = realFont();
    if ( mAttributes.autoShrink() )
        f.setPointSizeF( fitFontSizeToGeometry() );
    painter->setFont( f );
    QRectF rect( geometry() );

// #ifdef DEBUG_ITEMS_PAINT
//     painter->setPen( Qt::black );
//     painter->drawRect( rect );
// #endif
    painter->translate( rect.center() );
    rect.moveTopLeft( QPointF( - rect.width() / 2, - rect.height() / 2 ) );
#ifdef DEBUG_ITEMS_PAINT
    painter->setPen( Qt::blue );
    painter->drawRect( rect );
    painter->drawRect( QRect(QPoint((rect.topLeft().toPoint()  + rect.bottomLeft().toPoint())  / 2 - QPoint(2,2)), QSize(3,3)) );
    //painter->drawRect( QRect(QPoint((rect.topRight().toPoint() + rect.bottomRight().toPoint()) / 2 - QPoint(2,2)), QSize(3,3)) );
#endif
    painter->rotate( mAttributes.rotation() );
    rect = rotatedRect( rect, mAttributes.rotation() );
#ifdef DEBUG_ITEMS_PAINT
    painter->setPen( Qt::red );
    painter->drawRect( rect );
    painter->drawRect( QRect(QPoint((rect.topLeft().toPoint()  + rect.bottomLeft().toPoint())  / 2 - QPoint(2,2)), QSize(3,3)) );
    //painter->drawRect( QRect(QPoint((rect.topRight().toPoint() + rect.bottomRight().toPoint()) / 2 - QPoint(2,2)), QSize(3,3)) );
#endif
    painter->setPen( PrintingParameters::scalePen( mAttributes.pen() ) );
//    QTextDocument* document = mAttributes.textDocument();
//    if ( document ) {
//        document->setPageSize(QSize(rect.width(), rect.height()));
//        document->setHtml(mText);
//        QAbstractTextDocumentLayout::PaintContext paintcontext;
//        paintcontext.clip = rect;
//        document->documentLayout()->draw(painter, paintcontext);
//    } else {
        painter->drawText( rect, mTextAlignment, mText );
//    }

//    if (  calcSizeHint( realFont() ).width() > rect.width() )
//        qDebug() << "rect.width()" << rect.width() << "text.width()" << calcSizeHint( realFont() ).width();
//
//    //painter->drawText( rect, Qt::AlignHCenter | Qt::AlignVCenter, mText );
}
void MusicRoundAnimationLabel::paintEvent(QPaintEvent *event)
{
    QWidget::paintEvent(event);
    QPainter painter(this);

    QSize self = size();
    QRect rotatedRect(-self.width()/2, -self.height()/2, self.width(), self.height());
    int cx = self.width() / 2;
    int cy = self.height() / 2;

    if(++m_rotateAngle >= MA_360)
    {
        m_rotateAngle -= MA_360;
    }

    painter.save();
    painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    painter.translate(cx, cy);
    painter.rotate(m_rotateAngle);
    painter.drawPixmap(rotatedRect, m_pixmap);
    painter.restore();
}
void ForestDetector::detect(cv::Mat& image, std::string imageName)//deuxième paramètre peut-être à supprimer
{
	cv::namedWindow("lol");
    cv::namedWindow("detection");
    cv::namedWindow("hough");
	cv::Mat integral;
    cv::cvtColor(image, integral, CV_RGB2GRAY);//Convert image to grayscale image
    cv::integral(integral, integral);
	int height = image.size().height;
	int width = image.size().width;
	unsigned int patchWidth = _pForestEnv->getPatchWidth();
	unsigned int patchHeight = _pForestEnv->getPatchHeight();
	
	float currentMax=0;
	double pas=2;
	
	//std::vector<Patch*> vecPatch(nbPatch);
    cv::Mat result = cv::Mat::zeros(image.size().height/pas, image.size().width/pas, CV_32F);
	cv::Mat angle = cv::Mat::zeros(image.size().height/pas, image.size().width/pas, CV_64F);

	std::vector<cv::Point_<int> > offsetMeans;
	std::vector<cv::Point_<double> > offsetVar;
	std::vector<int> nbPatchs;

	cv::Mat imRoi, imIntRoi;

    double roll=0;
    double meanRoll=0;

    std::vector<Leaf*> detectionVotes;
	std::vector<cv::Mat> detectionMeans;
	
    for (int x=0 ; x < width-patchWidth ; x+=pas)//cols
	{
        for (int y=0 ; y < height-patchHeight ; y+=pas)//rows
		{
			cv::Rect_<int> roi(x, y, patchWidth, patchHeight);
			cv::Rect_<int> roiInt(x, y, patchWidth+1, patchHeight+1); //patch
            cv::Mat meanSV;
			std::vector<cv::Mat> patchs;
            double conf=0;


			image(roi).copyTo(imRoi);
			integral(roiInt).copyTo(imIntRoi);

			//patchs.push_back(image(roi).clone());
			//patchs.push_back(integral(roiInt).clone());

			patchs.push_back(imRoi);
			patchs.push_back(imIntRoi);



			Patch patch(patchs, roi);
			
			std::vector<Leaf*> detectedLeaf;
			pForest->regression(patch, detectedLeaf);


            double test=0;
            double denom=0;

			for (int i=0 ; i<detectedLeaf.size() ; i++)
			{

				offsetMeans.push_back(detectedLeaf[i]->getMeanOffsets());
				offsetVar.push_back(detectedLeaf[i]->getVarOffsets());
				nbPatchs.push_back(detectedLeaf[i]->getNumberPatchs());
				meanSV = detectedLeaf[i]->getSVMean().clone();
                conf = detectedLeaf[i]->getConf();



				//std::cout << offsetMeans.back() << " " << offsetVar.back() << " " << nbPatchs.back() << std::endl;
				cv::Point_<int> offset(-offsetMeans.back().x+patchWidth/2+x, -offsetMeans.back().y+patchHeight/2+y);
				if (offset.x >= 0 && offset.x < width && offset.y >= 0 && offset.y < height)
				{
                    offset.x = offset.x/pas;
                    offset.y = offset.y/pas;
					//if ((offsetVar.back().x <= 200) && (offsetVar.back().y <= 200))
					if ((conf == 1) && (detectedLeaf[i]->getTrace() < 500))
                    {
                        //result.at<float>(offset) += 1.*float(1./(sqrt(offsetVar.back().x*offsetVar.back().x+offsetVar.back().y*offsetVar.back().y)));
                        detectionVotes.push_back(detectedLeaf[i]);
						detectionMeans.push_back(detectedLeaf[i]->getSVMean().clone());
						detectionMeans.back().at<double>(0) = offset.x;
						detectionMeans.back().at<double>(1) = offset.y;
                        result.at<float>(offset) += conf;
                        //result.at<float>(offset) += detectedLeaf[i]->getNumberPatchs();
                        //result.at<float>(offset) += 1.*float(nbPatchs.back()/sqrt(offsetVar.back().x*offsetVar.back().y));
                        //result.at<float>(offset) += 1.*float(nbPatchs.back()/sqrt(offsetVar.back().x*offsetVar.back().x+offsetVar.back().y*offsetVar.back().y));
                        //roll += meanSV.at<double>(6)*conf;
                        denom+=conf;
                        test+=conf*meanSV.at<double>(4);
                        //std::cout << "cooooooooonf : " << test*20 << std::endl;
                        angle.at<double>(y/pas, x/pas) = test/denom;
                        //if (test > maxAngle) maxAngle = test;
                        //if (test < minAngle) minAngle = test;

                        //meanRoll += conf;
                    }
                    else
                    {
                        angle.at<double>(y/pas, x/pas) = -100;
                    }
                    if (result.at<float>(offset) > currentMax) currentMax=result.at<float>(offset);
				}
			}

		}
	}

	if (detectionMeans.size()==0) std::cout << "no detection" << std::endl;

	MeanShift ms(detectionMeans);
	cv::Mat mean;
	ms.getMaxCluster(detectionMeans, mean);

	//cv::Mat imageToSave = result/currentMax;
	//cv::imwrite("../output/"+imageName, result);

	//std::cout << result.depth() << std::endl;
	//std::cout << result.size().height << " " << result.size().width << std::endl;
	result=result/currentMax*255;
    result.convertTo(result, CV_8U);

    //std::cout << "angle : " << angle << std::endl;
    angle=(angle+22)/45*255;
    angle.convertTo(angle, CV_8U);
    cv::applyColorMap(angle, angle, cv::COLORMAP_JET);
    cv::imshow("hough", angle);

	//cv::Rect rect(result.cols/2-50, result.rows/2-50, 50, 50);

	/*cv::RotatedRect rotatedRect(cv::Point2f(result.cols/pas-50/pas, result.rows/pas), cv::Size2f(50/pas, 50/pas), 0);
    for (int i=0 ; i<2 ; i++)
	{
		cv::Rect rect = rotatedRect.boundingRect();
		rotatedRect = cv::CamShift(result, rect, cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 10, 1));
	}*/
	cv::RotatedRect rotatedRect(cv::Point2f(mean.at<double>(0), mean.at<double>(1)), cv::Size2f(128/pas, 128/pas), 0);
	std::cout << mean.at<double>(3) << " " << mean.at<double>(4) << " " << mean.at<double>(5) << std::endl;

	cv::Mat imageToSave=result.clone();
	cv::ellipse(imageToSave, rotatedRect, cv::Scalar_<int>(0,255,0), 2);
    rotatedRect.center = rotatedRect.center*pas;
    rotatedRect.size.height = rotatedRect.size.height*pas;
    rotatedRect.size.width = rotatedRect.size.width*pas;
    rotatedRect.angle = roll/meanRoll;

    //cv::rectangle(image, rotatedRect.boundingRect(), cv::Scalar_<int>(125,255,125), 2);
    cv::ellipse(image, rotatedRect, cv::Scalar_<int>(125,255,125), 2);


	cv::applyColorMap(imageToSave, imageToSave, cv::COLORMAP_JET);
    cv::imwrite("../output/"+imageName, angle);
    cv::imshow("detection", image);
	cv::imshow("lol", imageToSave);

	cv::waitKey(5000);
	
}
void ForestDetector::detect(std::vector<std::vector<double> >& vGroundTruth, std::vector<std::string>& vPaths, cv::Size_<int>& templateSize, std::vector<cv::Point_<int> >& vCenters)
{
	std::ostringstream oss;
	oss << "../output/result_learning_" << _index << ".txt" << std::endl;
	std::fstream fileRes(oss.str().c_str(), std::fstream::out);


	for (int imageInd=0 ; imageInd < vPaths.size() ; imageInd++)
	{

		cv::Mat image = cv::imread(vPaths.at(imageInd), CV_LOAD_IMAGE_GRAYSCALE);
		cv::Mat integral;
		cv::namedWindow("lol");
		cv::namedWindow("detection");
		cv::namedWindow("hough");
		cv::integral(image, integral);

		int height = image.size().height;
		int width = image.size().width;
		unsigned int patchWidth = _pForestEnv->getPatchWidth();
		unsigned int patchHeight = _pForestEnv->getPatchHeight();

		float currentMax=0;
		double pas=2;

		//For display
		cv::Mat result = cv::Mat::zeros(image.size().height/pas, image.size().width/pas, CV_32F);
		cv::Mat angle = cv::Mat::zeros(image.size().height/pas, image.size().width/pas, CV_64F);

		std::vector<cv::Point_<int> > offsetMeans;
		std::vector<cv::Point_<double> > offsetVar;
		std::vector<int> nbPatchs;

		cv::Mat imRoi, imIntRoi;

		std::vector<Leaf*> detectionVotes;
		std::vector<cv::Mat> detectionMeans;

		for (int x=0 ; x < width-patchWidth ; x+=pas)//cols
		{
			for (int y=0 ; y < height-patchHeight ; y+=pas)//rows
			{
				cv::Rect_<int> roi(x, y, patchWidth, patchHeight);
				cv::Rect_<int> roiInt(x, y, patchWidth+1, patchHeight+1); //patch
				cv::Mat meanSV;
				std::vector<cv::Mat> patchs;
				double conf=0;


				image(roi).copyTo(imRoi);
				integral(roiInt).copyTo(imIntRoi);

				patchs.push_back(imRoi);
				patchs.push_back(imIntRoi);

				Patch patch(patchs, roi);

				std::vector<Leaf*> detectedLeaf;
				pForest->regression(patch, detectedLeaf);

				double test=0;
				double denom=0;

				for (int i=0 ; i<detectedLeaf.size() ; i++)
				{

					offsetMeans.push_back(detectedLeaf[i]->getMeanOffsets());
					offsetVar.push_back(detectedLeaf[i]->getVarOffsets());
					nbPatchs.push_back(detectedLeaf[i]->getNumberPatchs());
					meanSV = detectedLeaf[i]->getSVMean().clone();
					conf = detectedLeaf[i]->getConf();



					//std::cout << offsetMeans.back() << " " << offsetVar.back() << " " << nbPatchs.back() << std::endl;
					cv::Point_<int> offset(-offsetMeans.back().x+patchWidth/2+x, -offsetMeans.back().y+patchHeight/2+y);
					if (offset.x >= 0 && offset.x < width && offset.y >= 0 && offset.y < height)
					{
						offset.x = offset.x/pas;
						offset.y = offset.y/pas;
						//if ((offsetVar.back().x <= 200) && (offsetVar.back().y <= 200))
						if ((conf == 1) && (detectedLeaf[i]->getTrace() < 500))
						{
							detectionVotes.push_back(detectedLeaf[i]);
							detectionMeans.push_back(detectedLeaf[i]->getSVMean().clone());
							detectionMeans.back().at<double>(0) = offset.x*pas;
							detectionMeans.back().at<double>(1) = offset.y*pas;


							//Might be removed => only for display (and maybe detection with particle filtering)
							result.at<float>(offset) += conf;
							denom+=conf;
							test+=conf*meanSV.at<double>(4);
							angle.at<double>(y/pas, x/pas) = test/denom;

						}
						else
						{
							//still for display
							angle.at<double>(y/pas, x/pas) = -100;
						}
						//display as well
						if (result.at<float>(offset) > currentMax) currentMax=result.at<float>(offset);
					}
				}//End of leaf loop

			}//End of rows loop
		}//End of cols loop

		if (detectionMeans.size()==0)
		{
			std::cout << "no detection" << std::endl;
			continue;
		}

		//Detection with mean shift
		MeanShift ms(detectionMeans);
		cv::Mat mean;
		ms.getMaxCluster(detectionMeans, mean);

		//For display
		result=result/currentMax*255;
		result.convertTo(result, CV_8U);
		angle=(angle+22)/45*255;
		angle.convertTo(angle, CV_8U);
		cv::applyColorMap(angle, angle, cv::COLORMAP_JET);
		cv::imshow("hough", angle);

		//Write in result file
		fileRes << vPaths[imageInd] << " ";//Image
		fileRes << vGroundTruth[imageInd].at(1) << " "<< vGroundTruth[imageInd].at(2) << " "<< vGroundTruth[imageInd].at(3) << " " << vGroundTruth[imageInd].at(4) << " " << vGroundTruth[imageInd].at(5) << " " << vGroundTruth[imageInd].at(6) << " ";//Ground Truth
		fileRes << mean.at<double>(0) << " " << mean.at<double>(1) << " " << mean.at<double>(2) << " " << mean.at<double>(3) << " " << mean.at<double>(4) << " " << mean.at<double>(5) << std::endl;//Detection
		//End of write

		cv::RotatedRect rotatedRect(cv::Point2f(mean.at<double>(0)-128/(2*pas), mean.at<double>(1)-128/(2*pas)), cv::Size2f(128/(2*pas), 128/(2*pas)), 0);
		//std::cout << mean.at<double>(3) << " " << mean.at<double>(4) << " " << mean.at<double>(5) << std::endl;

		cv::Mat imageToSave=result.clone();
		cv::ellipse(imageToSave, rotatedRect, cv::Scalar_<int>(0,255,0), 2);
		rotatedRect.center = rotatedRect.center*pas;
		rotatedRect.size.height = rotatedRect.size.height*pas;
		rotatedRect.size.width = rotatedRect.size.width*pas;

		cv::ellipse(image, rotatedRect, cv::Scalar_<int>(125,255,125), 2);


		cv::applyColorMap(imageToSave, imageToSave, cv::COLORMAP_JET);
		cv::imshow("detection", image);
		cv::imshow("lol", imageToSave);

		cv::waitKey(50);

	}//End of images loop
}
void clTabRendererCurved::Draw(wxDC& dc, const clTabInfo& tabInfo, const clTabColours& colours, size_t style)
{
    const int TOP_SMALL_HEIGHT = 0;
    wxColour bgColour(tabInfo.IsActive() ? colours.activeTabBgColour : colours.inactiveTabBgColour);
    wxColour penColour(tabInfo.IsActive() ? colours.activeTabPenColour : colours.inactiveTabPenColour);
    wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
    dc.SetTextForeground(tabInfo.IsActive() ? colours.activeTabTextColour : colours.inactiveTabTextColour);
    dc.SetFont(font);

    if(style & kNotebook_BottomTabs) {
        // Bottom tabs
        {
            wxPoint points[6];
            points[0] = tabInfo.m_rect.GetTopLeft();

            points[1].x = points[0].x + majorCurveWidth;
            points[1].y = tabInfo.m_rect.GetBottomLeft().y - TOP_SMALL_HEIGHT;

            points[2].x = points[1].x + smallCurveWidth;
            points[2].y = points[1].y + TOP_SMALL_HEIGHT;

            points[3].x = points[0].x + (tabInfo.m_rect.GetWidth() - (majorCurveWidth + smallCurveWidth));
            points[3].y = points[2].y;

            points[4].x = points[3].x + smallCurveWidth;
            points[4].y = points[1].y;

            points[5] = tabInfo.m_rect.GetTopRight();

            dc.SetPen(penColour);
            dc.SetBrush(bgColour);
            dc.DrawPolygon(6, points);
        }
        {
            wxPoint points[6];
            points[0] = tabInfo.m_rect.GetTopLeft();
            points[0].x += 1;

            points[1].x = points[0].x + majorCurveWidth;
            points[1].y = tabInfo.m_rect.GetBottomLeft().y - TOP_SMALL_HEIGHT - 1;

            points[2].x = points[1].x + smallCurveWidth;
            points[2].y = points[1].y + TOP_SMALL_HEIGHT;

            points[3].x = points[0].x + (tabInfo.m_rect.GetWidth() - 2 - (majorCurveWidth + smallCurveWidth));
            points[3].y = points[2].y;

            points[4].x = points[3].x + smallCurveWidth;
            points[4].y = points[1].y;

            points[5] = tabInfo.m_rect.GetTopRight();
            points[5].x -= 2;

            dc.SetPen(tabInfo.IsActive() ? colours.activeTabInnerPenColour : colours.inactiveTabInnerPenColour);
            dc.SetBrush(bgColour);
            dc.DrawPolygon(6, points);
        }
    } else if(IS_VERTICAL_TABS(style)) {

        // Left side tabs
        wxRect rotatedRect(0, 0, tabInfo.m_rect.GetHeight(), tabInfo.m_rect.GetWidth());
        wxBitmap b(rotatedRect.GetSize());

        wxMemoryDC tmpDC(b);
        tmpDC.SetPen(colours.tabAreaColour);
        tmpDC.SetBrush(colours.tabAreaColour);
        tmpDC.DrawRectangle(rotatedRect);
        tmpDC.SetFont(font);
        tmpDC.SetTextForeground(tabInfo.IsActive() ? colours.activeTabTextColour : colours.inactiveTabTextColour);

        tmpDC.SetPen(penColour);
        tmpDC.SetBrush(bgColour);
        if(tabInfo.IsActive()) {
            {
                wxPoint points[6];
                points[0] = rotatedRect.GetBottomLeft();
                points[1].x = points[0].x + majorCurveWidth;
                points[1].y = rotatedRect.GetLeftTop().y + TOP_SMALL_HEIGHT;

                points[2].x = points[1].x + smallCurveWidth;
                points[2].y = points[1].y - TOP_SMALL_HEIGHT;

                points[3].x = points[0].x + (rotatedRect.GetWidth() - (majorCurveWidth + smallCurveWidth));
                points[3].y = points[2].y;

                points[4].x = points[3].x + smallCurveWidth;
                points[4].y = points[3].y + TOP_SMALL_HEIGHT;

                points[5] = rotatedRect.GetBottomRight();

                tmpDC.SetPen(penColour);
                tmpDC.SetBrush(bgColour);
                tmpDC.DrawPolygon(6, points);
            }

            {
                wxPoint points[6];
                points[0] = rotatedRect.GetBottomLeft();
                points[0].x += 1;

                points[1].x = points[0].x + majorCurveWidth;
                points[1].y = rotatedRect.GetLeftTop().y + TOP_SMALL_HEIGHT + 1;

                points[2].x = points[1].x + smallCurveWidth;
                points[2].y = points[1].y - TOP_SMALL_HEIGHT;

                points[3].x = points[0].x + (rotatedRect.GetWidth() - 2 - (majorCurveWidth + smallCurveWidth));
                points[3].y = points[2].y;

                points[4].x = points[3].x + smallCurveWidth;
                points[4].y = points[3].y + TOP_SMALL_HEIGHT;

                points[5] = rotatedRect.GetBottomRight();
                points[5].x -= 2;

                tmpDC.SetPen(tabInfo.IsActive() ? colours.activeTabInnerPenColour : colours.inactiveTabInnerPenColour);
                tmpDC.SetBrush(bgColour);
                tmpDC.DrawPolygon(6, points);
            }
        } else {
            // Inactive tabs
            wxDirection direction = wxNORTH;
            wxPoint basePoint = ((style & kNotebook_LeftTabs) ? rotatedRect.GetLeftTop() : rotatedRect.GetRightTop());
            {
                wxPoint pt = basePoint;
                pt.x -= 1;
                wxRect gr(pt, wxSize(1, rotatedRect.GetHeight()));
                tmpDC.SetPen(*wxTRANSPARENT_PEN);
                tmpDC.GradientFillLinear(gr, colours.inactiveTabPenColour, bgColour, direction);
            }
            {
                wxPoint pt = basePoint;
                wxRect gr(pt, wxSize(1, rotatedRect.GetHeight()));
                tmpDC.SetPen(*wxTRANSPARENT_PEN);
                tmpDC.GradientFillLinear(gr, colours.inactiveTabInnerPenColour, bgColour, direction);
            }
            {
                wxPoint pt = basePoint;
                pt.x += 1;
                wxRect gr(pt, wxSize(1, rotatedRect.GetHeight()));
                tmpDC.SetPen(*wxTRANSPARENT_PEN);
                tmpDC.GradientFillLinear(gr, colours.inactiveTabPenColour, bgColour, direction);
            }
        }

        // Vertical tabs
        // Draw bitmap
        if(tabInfo.GetBitmap().IsOk()) {
            tmpDC.DrawBitmap(tabInfo.GetBitmap(), tabInfo.m_bmpY, tabInfo.m_bmpX);
        }

        tmpDC.DrawText(tabInfo.m_label, tabInfo.m_textY, tabInfo.m_textX);
        if(tabInfo.IsActive() && (style & kNotebook_CloseButtonOnActiveTab)) {
            tmpDC.DrawBitmap(colours.closeButton, tabInfo.m_bmpCloseY, tabInfo.m_bmpCloseX);
        }
        tmpDC.SelectObject(wxNullBitmap);
        wxImage img = b.ConvertToImage();
        img = img.Rotate90((style & kNotebook_RightTabs));
        b = wxBitmap(img);
        dc.DrawBitmap(b, tabInfo.m_rect.GetTopLeft());

    } else {
        // Default tabs (placed at the top)
        {
            wxPoint points[6];
            points[0] = tabInfo.m_rect.GetBottomLeft();

            points[1].x = points[0].x + majorCurveWidth;
            points[1].y = tabInfo.m_rect.GetLeftTop().y + TOP_SMALL_HEIGHT;

            points[2].x = points[1].x + smallCurveWidth;
            points[2].y = points[1].y - TOP_SMALL_HEIGHT;

            points[3].x = points[0].x + (tabInfo.m_rect.GetWidth() - (majorCurveWidth + smallCurveWidth));
            points[3].y = points[2].y;

            points[4].x = points[3].x + smallCurveWidth;
            points[4].y = points[3].y + TOP_SMALL_HEIGHT;

            points[5] = tabInfo.m_rect.GetBottomRight();

            dc.SetPen(penColour);
            dc.SetBrush(bgColour);
            dc.DrawPolygon(6, points);
        }

        {
            wxPoint points[6];
            points[0] = tabInfo.m_rect.GetBottomLeft();
            points[0].x += 1;

            points[1].x = points[0].x + majorCurveWidth;
            points[1].y = tabInfo.m_rect.GetLeftTop().y + TOP_SMALL_HEIGHT + 1;

            points[2].x = points[1].x + smallCurveWidth;
            points[2].y = points[1].y - TOP_SMALL_HEIGHT;

            points[3].x = points[0].x + (tabInfo.m_rect.GetWidth() - 2 - (majorCurveWidth + smallCurveWidth));
            points[3].y = points[2].y;

            points[4].x = points[3].x + smallCurveWidth;
            points[4].y = points[3].y + TOP_SMALL_HEIGHT;

            points[5] = tabInfo.m_rect.GetBottomRight();
            points[5].x -= 2;

            dc.SetPen(tabInfo.IsActive() ? colours.activeTabInnerPenColour : colours.inactiveTabInnerPenColour);
            dc.SetBrush(bgColour);
            dc.DrawPolygon(6, points);
        }
    }

    if(!IS_VERTICAL_TABS(style)) {
        // Draw bitmap
        if(tabInfo.GetBitmap().IsOk()) {
            dc.DrawBitmap(tabInfo.GetBitmap(), tabInfo.m_bmpX + tabInfo.m_rect.GetX(), tabInfo.m_bmpY);
        }
        dc.DrawText(tabInfo.m_label, tabInfo.m_textX + tabInfo.m_rect.GetX(), tabInfo.m_textY);
        if(tabInfo.IsActive() && (style & kNotebook_CloseButtonOnActiveTab)) {
            dc.DrawBitmap(colours.closeButton, tabInfo.m_bmpCloseX + tabInfo.m_rect.GetX(), tabInfo.m_bmpCloseY);
        }
    }
}