Ejemplo n.º 1
0
	virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const {
		Common::String filename = generateGameStateFileName(target, slot);
		Common::ScopedPtr<Common::InSaveFile> in(g_system->getSavefileManager()->openForLoading(filename));
		if (!in)
			return SaveStateDescriptor();

		char buf[25];
		in->seek(0);
		in->read(buf, 24);
		buf[24] = 0;

		Common::String desc = buf;

		in->seek(0x777a);
		if (!Graphics::checkThumbnailHeader(*in))
			return SaveStateDescriptor(slot, desc);

		SaveStateDescriptor ssd(slot, desc);
		ssd.setDeletableFlag(true);

		//checking for the thumbnail
		Common::ScopedPtr<Graphics::Surface> thumb(new Graphics::Surface);
		if (Graphics::loadThumbnail(*in, *thumb))
			ssd.setThumbnail(thumb.release());

		return ssd;
	}
Ejemplo n.º 2
0
int main(int argc, char* argv[])
{
	arm();
	thumb();
        printf("arm: %d\n", (ptrdiff_t) &arm);
        printf("thumb: %d\n", (ptrdiff_t) &thumb);
	return 0;
}
Ejemplo n.º 3
0
const QPixmap ImageItem::pixmap() {
    if (!lock.tryLock()) return QPixmap();
    thumbnail();
    if (!thumb.valid()) {
        lock.unlock();
        return QPixmap();
    } else if (!pix) {
        QImage thumbQ(thumb(0,0), 640, 480, QImage::Format_RGB888);
        pix.reset(new QPixmap(QPixmap::fromImage(thumbQ)));
    } 
    lock.unlock();
    return *pix;
}
Ejemplo n.º 4
0
void ProfileTest::testRemoveFavoriteThumb()
{
	Favorite fav("tag_1", 20, QDateTime(QDate(2016, 9, 1), QTime(9, 23, 17)));

	QDir(m_profile->getPath()).mkdir("thumb");
	QFile thumb(m_profile->getPath() + "/thumbs/" + fav.getName(true) + ".png");
	thumb.open(QFile::WriteOnly | QFile::Truncate);
	thumb.write(QString("test").toUtf8());
	thumb.close();

	QVERIFY(thumb.exists());
	m_profile->removeFavorite(fav);
	QVERIFY(!thumb.exists());
}
Ejemplo n.º 5
0
QImage JpegContent::thumbnail() const
{
    QImage image;
    if (!d->mExifData.empty()) {
#if(EXIV2_TEST_VERSION(0,17,91))
        Exiv2::ExifThumbC thumb(d->mExifData);
        Exiv2::DataBuf thumbnail = thumb.copy();
#else
        Exiv2::DataBuf thumbnail = d->mExifData.copyThumbnail();
#endif
        image.loadFromData(thumbnail.pData_, thumbnail.size_);
    }
    return image;
}
Ejemplo n.º 6
0
ThemeSliderView::ThemeSliderView()
{
	set_horizontal();

	style()->set("flex-direction: row;");
	track()->style()->set("flex: 1 1 main-size;");
	track()->style()->set("height: 4px;");
	track()->style()->set("margin: 7px 0px");
	track()->style()->set("border-image-slice: 1 2 1 1 fill;");
	track()->style()->set("border-image-width:1px 2px 1px 1px;");
	track()->style()->set("border-image-repeat:stretch;");
	track()->style()->set("border-image-source:url('Theme/slider_track.png');");

	thumb()->style()->set("position: absolute;");
	thumb()->style()->set("width:11px;");
	thumb()->style()->set("height:19px;");
	thumb()->style()->set("border-image-slice:9 3 9 2 fill;");
	thumb()->style()->set("border-image-width:9px 3px 9px 2px;");
	thumb()->style()->set("border-image-repeat:stretch;");
	thumb()->style()->set("border-image-source:url('Theme/slider_horizontal_thumb_normal.png');");
	thumb()->style("hot")->set("border-image-source:url('Theme/slider_horizontal_thumb_hot.png');");
	thumb()->style("pressed")->set("border-image-source:url('Theme/slider_horizontal_thumb_pressed.png');");
	thumb()->style("disabled")->set("border-image-source:url('Theme/slider_horizontal_thumb_disabled.png');");
}
Ejemplo n.º 7
0
void UBThumbnailAdaptor::persistScene(UBDocumentProxy* proxy, UBGraphicsScene* pScene, int pageIndex, bool overrideModified)
{
    QString fileName = proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", pageIndex);

    QFile thumbFile(fileName);

    if (pScene->isModified() || overrideModified || !thumbFile.exists() || UBApplication::boardController->paletteManager()->teacherGuideDockWidget()->teacherGuideWidget()->isModified())
    {
        qreal nominalWidth = pScene->nominalSize().width();
        qreal nominalHeight = pScene->nominalSize().height();
        qreal ratio = nominalWidth / nominalHeight;
        QRectF sceneRect = pScene->normalizedSceneRect(ratio);

        qreal width = UBSettings::maxThumbnailWidth;
        qreal height = width / ratio;

        QImage thumb(width, height, QImage::Format_ARGB32);

        QRectF imageRect(0, 0, width, height);

        QPainter painter(&thumb);
        painter.setRenderHint(QPainter::Antialiasing, true);
        painter.setRenderHint(QPainter::SmoothPixmapTransform, true);

        if (pScene->isDarkBackground())
        {
            painter.fillRect(imageRect, Qt::black);
        }
        else
        {
            painter.fillRect(imageRect, Qt::white);
        }

        pScene->setRenderingQuality(UBItem::RenderingQualityHigh);

        pScene->render(&painter, imageRect, sceneRect, Qt::KeepAspectRatio);

        if(UBApplication::boardController->paletteManager()->teacherGuideDockWidget()->teacherGuideWidget()->isModified()){
            QPixmap toque(":images/toque.svg");
            painter.setOpacity(0.6);
            painter.drawPixmap(QPoint(width - toque.width(),0),toque);
        }

        pScene->setRenderingQuality(UBItem::RenderingQualityNormal);

        thumb.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation).save(fileName, "JPG");
    }
}
Ejemplo n.º 8
0
void UBThumbnailAdaptor::persistScene(UBDocumentProxy* proxy, UBGraphicsScene* pScene, int pageIndex, bool overrideModified)
{

    qDebug() << "Persist scene on path " << proxy->persistencePath() << ", index " << pageIndex;

    QString fileName = proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", pageIndex);

    QFile thumbFile(fileName);

    if (pScene->isModified() || overrideModified || !thumbFile.exists())
    {
        qreal nominalWidth = pScene->nominalSize().width();
        qreal nominalHeight = pScene->nominalSize().height();
        qreal ratio = nominalWidth / nominalHeight;
        QRectF sceneRect = pScene->normalizedSceneRect(ratio);

        qreal width = UBSettings::maxThumbnailWidth;
        qreal height = width / ratio;

        QImage thumb(width, height, QImage::Format_ARGB32);

        QRectF imageRect(0, 0, width, height);

        QPainter painter(&thumb);
        painter.setRenderHint(QPainter::Antialiasing, true);
        painter.setRenderHint(QPainter::SmoothPixmapTransform, true);

        if (pScene->isDarkBackground())
        {
            painter.fillRect(imageRect, Qt::black);
        }
        else
        {
            painter.fillRect(imageRect, Qt::white);
        }

        pScene->setRenderingContext(UBGraphicsScene::NonScreen);
        pScene->setRenderingQuality(UBItem::RenderingQualityHigh);

        pScene->render(&painter, imageRect, sceneRect, Qt::KeepAspectRatio);

        pScene->setRenderingContext(UBGraphicsScene::Screen);
        pScene->setRenderingQuality(UBItem::RenderingQualityNormal);

        thumb.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation).save(fileName, "JPG");
    }
}
Ejemplo n.º 9
0
void CFanart::Pack()
{
  // Take our data and pack it into the m_xml string
  m_xml.clear();
  TiXmlElement fanart("fanart");
  for (std::vector<SFanartData>::const_iterator it = m_fanart.begin(); it != m_fanart.end(); ++it)
  {
    TiXmlElement thumb("thumb");
    thumb.SetAttribute("dim", it->strResolution.c_str());
    thumb.SetAttribute("colors", it->strColors.c_str());
    thumb.SetAttribute("preview", it->strPreview.c_str());
    TiXmlText text(it->strImage);
    thumb.InsertEndChild(text);
    fanart.InsertEndChild(thumb);
  }
  m_xml << fanart;
}
Ejemplo n.º 10
0
ThemeScrollBarView::ThemeScrollBarView()
{
	set_horizontal();
	style()->set("flex: 0 0 main-size");
	style()->set("background: rgb(232, 232, 236)");
	track()->style()->set("border-image-slice: 4 0 3 0 fill;");
	track()->style()->set("border-image-width:4px 0px 3px 0px;");
	track()->style()->set("border-image-repeat:stretch;");
	track()->style()->set("border-image-source:url('Theme/scrollbar_hori_track_normal.png');");
	track()->style("hot")->set("border-image-source:url('Theme/scrollbar_hori_track_hot.png');");
	track()->style("pressed")->set("border-image-source:url('Theme/scrollbar_hori_track_pressed.png');");
	track()->style("disabled")->set("border-image-source:url('Theme/scrollbar_hori_track_disabled.png');");

	thumb()->style()->set("border-image-slice: 5 5 5 5 fill;");
	thumb()->style()->set("border-image-width:5px 5px 5px 5px;");
	thumb()->style()->set("border-image-repeat:stretch;");
	thumb()->style()->set("border-image-source:url('Theme/scrollbar_hori_thumb_normal.png');");
	thumb()->style("hot")->set("border-image-source:url('Theme/scrollbar_hori_thumb_hot.png');");
	thumb()->style("pressed")->set("border-image-source:url('Theme/scrollbar_hori_thumb_pressed.png');");
	thumb()->style("disabled")->set("border-image-source:url('Theme/scrollbar_hori_thumb_disabled.png');");

	thumb_grip()->style()->set("background-position:center center;");
	thumb_grip()->style()->set("background-repeat:no-repeat;");
	thumb_grip()->style()->set("background-attachment:scroll; ");
	thumb_grip()->style()->set("background-image:url('Theme/scrollbar_hori_thumb_gripper_normal.png');");
	thumb_grip()->style("hot")->set("background-image:url('Theme/scrollbar_hori_thumb_gripper_hot.png');");
	thumb_grip()->style("pressed")->set("background-image:url('Theme/scrollbar_hori_thumb_gripper_pressed.png');");
	thumb_grip()->style("disabled")->set("background-image:url('Theme/scrollbar_hori_thumb_gripper_disabled.png');");

	button_decrement()->style()->set("width:17px; height:17px");
	button_decrement()->style()->set("border-image-slice: 3 3 3 3 fill;");
	button_decrement()->style()->set("border-image-width:3px 3px 3px 3px;");
	button_decrement()->style()->set("border-image-repeat:stretch;");
	button_decrement()->style()->set("border-image-source:url('Theme/scrollbar_hori_button_left_normal_withglyph.png');");
	button_decrement()->style("hot")->set("border-image-source:url('Theme/scrollbar_hori_button_left_hot_withglyph.png');");
	button_decrement()->style("pressed")->set("border-image-source:url('Theme/scrollbar_hori_button_left_pressed_withglyph.png');");
	button_decrement()->style("disabled")->set("border-image-source:url('Theme/scrollbar_hori_button_left_disabled_withglyph.png');");

	button_increment()->style()->set("width:17px; height:17px");
	button_increment()->style()->set("border-image-slice: 3 3 3 3 fill;");
	button_increment()->style()->set("border-image-width:3px 3px 3px 3px;");
	button_increment()->style()->set("border-image-repeat:stretch;");
	button_increment()->style()->set("border-image-source:url('Theme/scrollbar_hori_button_right_normal_withglyph.png');");
	button_increment()->style("hot")->set("border-image-source:url('Theme/scrollbar_hori_button_right_hot_withglyph.png');");
	button_increment()->style("pressed")->set("border-image-source:url('Theme/scrollbar_hori_button_right_pressed_withglyph.png');");
	button_increment()->style("disabled")->set("border-image-source:url('Theme/scrollbar_hori_button_right_disabled_withglyph.png');");
}
Ejemplo n.º 11
0
void drawgrid()
{

	if(selectedwindow()==3)
	{
		hidemouse();
		//setcolor(15);
		int x1,x2,y1,y2;
		for(int loopx=0;loopx<maxx;loopx++)
		{
			for(int loopy=0;loopy<maxy;loopy++)
			{
				x1=windows[3].x1+4+(loopx*size);
				x2=x1+size-1;
				y1=windows[3].y1+17+(loopy*size);
				y2=y1+size-1;

				if(graph[loopx][loopy]==16)
				{
					setfillstyle(1,7);
					bar(x1,y1,x2,y2);
					setcolor(8);
					line(x1,y1,x2,y2);
					line(x1,y2,x2,y1);

				}
				else
				{
					setfillstyle(1,graph[loopx][loopy]);
					bar(x1,y1,x2,y2);
				}
				setcolor(0);
				rectangle(x1,y1,x2+1,y2+1);

			}
		}
		thumb();
		showmouse();
	}
}
Ejemplo n.º 12
0
void JpegContent::setThumbnail(const QImage& thumbnail)
{
    if (d->mExifData.empty()) {
        return;
    }

    QByteArray array;
    QBuffer buffer(&array);
    buffer.open(QIODevice::WriteOnly);
    QImageWriter writer(&buffer, "JPEG");
    if (!writer.write(thumbnail)) {
        qCritical() << "Could not write thumbnail\n";
        return;
    }

#if (EXIV2_TEST_VERSION(0,17,91))
    Exiv2::ExifThumb thumb(d->mExifData);
    thumb.setJpegThumbnail((unsigned char*)array.data(), array.size());
#else
    d->mExifData.setJpegThumbnail((unsigned char*)array.data(), array.size());
#endif
}
Ejemplo n.º 13
0
void drawpixel(int x, int y)
{
		hidemouse();
		int x1=windows[3].x1+4+(x*size);
		int x2=x1+size-1;
		int y1=windows[3].y1+17+(y*size);
		int y2=y1+size-1;
		setfillstyle(1,graph[x][y]);
		if(graph[x][y]==16)
		{
			setfillstyle(1,7);
			bar(x1,y1,x2,y2);
			setcolor(8);
			line(x1,y1,x2,y2);
			line(x1,y2,x2,y1);
		}
		else bar(x1,y1,x2,y2);
		setcolor(0);
		rectangle(x1,y1,x2+1,y2+1);
		thumb();
		showmouse();
}
Ejemplo n.º 14
0
void CScraperUrl::AddElement(std::string url, std::string aspect, std::string referrer, std::string cache, bool post, bool isgz, int season)
{
  TiXmlElement thumb("thumb");
  thumb.SetAttribute("spoof", referrer);
  thumb.SetAttribute("cache", cache);
  if (post)
    thumb.SetAttribute("post", "yes");
  if (isgz)
    thumb.SetAttribute("gzip", "yes");
  if (season >= 0)
  {
    thumb.SetAttribute("season", StringUtils::Format("%i", season));
    thumb.SetAttribute("type", "season");
  }
  thumb.SetAttribute("aspect", aspect);
  TiXmlText text(url);
  thumb.InsertEndChild(text);
  m_xml << thumb;
  SUrlEntry nUrl;
  nUrl.m_url = url;
  nUrl.m_spoof = referrer;
  nUrl.m_post = post;
  nUrl.m_isgz = isgz;
  nUrl.m_cache = cache;
  if (season >= 0)
  {
    nUrl.m_type = URL_TYPE_SEASON;
    nUrl.m_season = season;
  }
  else
    nUrl.m_type = URL_TYPE_GENERAL;
  
  nUrl.m_aspect = aspect;

  m_url.push_back(nUrl);
}
Ejemplo n.º 15
0
void ThumbGenerator::loadFile(QImage& image, const QFileInfo& fi)
{
    static int sequence = 0;

    if (GalleryUtil::IsMovie(fi.filePath()))
    {
        bool thumbnailCreated = false;
        QDir tmpDir("/tmp/mythgallery");
        if (!tmpDir.exists())
        {
            if (!tmpDir.mkdir(tmpDir.absolutePath()))
            {
                LOG(VB_GENERAL, LOG_ERR,
                    "Unable to create temp dir for movie thumbnail creation: " +
                    tmpDir.absolutePath());
            }
        }

        if (tmpDir.exists())
        {
            QString thumbFile = QString("%1.png")
                .arg(++sequence,8,10,QChar('0'));

            QString cmd = "mythpreviewgen";
            QStringList args;
            args << logPropagateArgs.split(" ", QString::SkipEmptyParts);
            args << "--infile" << '"' + fi.absoluteFilePath() + '"';
            args << "--outfile" << '"' + tmpDir.filePath(thumbFile) + '"';

            MythSystemLegacy ms(cmd, args, kMSRunShell);
            ms.SetDirectory(tmpDir.absolutePath());
            ms.Run();
            if (ms.Wait() == GENERIC_EXIT_OK)
            {
                QFileInfo thumb(tmpDir.filePath(thumbFile));
                if (thumb.exists())
                {
                    QImage img(thumb.absoluteFilePath());
                    image = img;
                    thumbnailCreated = true;
                }
            }
        }

        if (!thumbnailCreated)
        {
            QImage *img = GetMythUI()->LoadScaleImage("gallery-moviethumb.png");
            if (img)
            {
                image = *img;
            }
        }
    }
    else
    {
#ifdef EXIF_SUPPORT
        // Try to get thumbnail from exif data
        ExifData *ed = exif_data_new_from_file(fi.absoluteFilePath()
                                               .toLocal8Bit().constData());
        if (ed && ed->data)
        {
            image.loadFromData(ed->data, ed->size);
        }

        if (ed)
            exif_data_free(ed);

        if (image.width() > m_width && image.height() > m_height)
            return;
#endif

#ifdef DCRAW_SUPPORT
        QString extension = fi.suffix();
        QSet<QString> dcrawFormats = DcrawFormats::getFormats();
        int rotateAngle;

        if (dcrawFormats.contains(extension) &&
            (rotateAngle = DcrawHandler::loadThumbnail(&image,
                                               fi.absoluteFilePath())) != -1 &&
            image.width() > m_width && image.height() > m_height)
        {
            if (rotateAngle != 0)
            {
                QMatrix matrix;
                matrix.rotate(rotateAngle);
                image = image.transformed(matrix);
            }

            return;
        }
#endif

        image.load(fi.absoluteFilePath());
    }
}
Ejemplo n.º 16
0
void ScrollBar::OnInitialized()
{
    suic::StylePtr & selfStyle = GetStyle();

    suic::StylePtr dBtn(selfStyle->GetStylePart(_T("DecreaseButton")));
    suic::StylePtr iBtn(selfStyle->GetStylePart(_T("IncreaseButton")));

    suic::StylePtr dPage(selfStyle->GetStylePart(_T("DecreasePage")));
    suic::StylePtr iPage(selfStyle->GetStylePart(_T("IncreasePage")));

    suic::StylePtr thumb(selfStyle->GetStylePart(_T("Thumb")));

    if (!dBtn && GetOwner())
    {
        dBtn = GetOwner()->FindResource(GetClassName() + _T(".DecreaseButton"));
        iBtn = GetOwner()->FindResource(GetClassName() + _T(".IncreaseButton"));
        dPage = GetOwner()->FindResource(GetClassName() + _T(".Track.Page"));
        thumb = GetOwner()->FindResource(GetClassName() + _T(".Track.Thumb"));
    }

    if (!iPage || iPage->Setters->GetCount() == 0)
    {
        iPage = dPage;
    }

    _decreasePage.SetOwner(this);

    _decreasePage.SetStyle(dPage);
    _increasePage.SetStyle(iPage);
    _thumb.SetStyle(thumb);

    _decreaseBtn.SetStyle(dBtn);
    _increaseBtn.SetStyle(iBtn);

    if (GetOrientation() == CoreFlags::Horizontal)
    {
        //
        // 附加事件
        //
        _decreasePage.MouseLButtonDown.Add(this, &ScrollBar::OnPageLeft);
        _increasePage.MouseLButtonDown.Add(this, &ScrollBar::OnPageRight);
        _thumb.MouseMove.Add(this, &ScrollBar::OnHorzTrack);

        _decreaseBtn.MouseLButtonDown.Add(this, &ScrollBar::OnLineLeft);
        _increaseBtn.MouseLButtonDown.Add(this, &ScrollBar::OnLineRight);
    }
    else
    {
        _decreasePage.MouseLButtonDown.Add(this, &ScrollBar::OnPageUp);
        _increasePage.MouseLButtonDown.Add(this, &ScrollBar::OnPageDown);
        _thumb.MouseMove.Add(this, &ScrollBar::OnVertTrack);

        _decreaseBtn.MouseLButtonDown.Add(this, &ScrollBar::OnLineUp);
        _increaseBtn.MouseLButtonDown.Add(this, &ScrollBar::OnLineDown);
    }

    _thumb.MouseLButtonDown.Add(this, &ScrollBar::OnBeginTrack);
    _thumb.MouseLButtonUp.Add(this, &ScrollBar::OnEndTrack);

    SetFocusable(false);
    
    // test code
    UpdateScrollLogic(500, false);
}
Ejemplo n.º 17
0
void ThumbGenerator::loadFile(QImage& image, const QFileInfo& fi)
{
    if (GalleryUtil::IsMovie(fi.filePath()))
    {
        bool thumbnailCreated = false;
        QDir tmpDir("/tmp/mythgallery");
        if (!tmpDir.exists())
        {
            if (!tmpDir.mkdir(tmpDir.absolutePath()))
            {
                VERBOSE(VB_IMPORTANT, "Unable to create temp dir for movie "
                        "thumbnail creation: " + tmpDir.absolutePath());
            }
        }

        if (tmpDir.exists())
        {
            QString cmd = "mplayer -nosound -frames 1 -vo png:z=6 \"" +
                          fi.absoluteFilePath() + "\"";
            MythSystem ms(cmd, kMSRunShell);
            ms.SetDirectory(tmpDir.absolutePath());
            ms.Run();
            if (ms.Wait() == GENERIC_EXIT_OK)
            {
                QFileInfo thumb(tmpDir.filePath("00000001.png"));
                if (thumb.exists())
                {
                    QImage img(thumb.absoluteFilePath());
                    image = img;
                    thumbnailCreated = true;
                }
            }
        }

        if (!thumbnailCreated)
        {
            QImage *img = GetMythUI()->LoadScaleImage("gallery-moviethumb.png");
            if (img)
            {
                image = *img;
            }
        }
    }
    else
    {
#ifdef EXIF_SUPPORT
        // Try to get thumbnail from exif data
        ExifData *ed = exif_data_new_from_file(fi.absoluteFilePath()
                                               .toLocal8Bit().constData());
        if (ed && ed->data)
        {
            image.loadFromData(ed->data, ed->size);
        }

        if (ed)
            exif_data_free(ed);

        if (image.width() > m_width && image.height() > m_height)
            return;
#endif

        image.load(fi.absoluteFilePath());
    }
}
Ejemplo n.º 18
0
static size_t MSGetInstructionWidthThumb(void *start) {
    uint16_t *thumb(reinterpret_cast<uint16_t *>(start));
    return T$32bit$i(thumb[0]) ? 4 : 2;
}
Ejemplo n.º 19
0
void checkgrid()
{
if(selectedwindow()==3)
{
	int x1,x2,y1,y2;
	if(mousestat()==1)
	{
		if(selected(1,0)==0)
		{
			for(int loopx=0;loopx<maxx;loopx++)
			{
				for(int loopy=0;loopy<maxy;loopy++)
				{
					x1=windows[3].x1+4+(loopx*size);
					x2=x1+size-1;
					y1=windows[3].y1+17+(loopy*size);
					y2=y1+size-1;
					if(x>=x1 && x<x2 && y>=y1 && y<y2)
					{
						graph[loopx][loopy]=selected(0,0);
						drawpixel(loopx,loopy);
					}
				}
			}
			thumb();
		}
	}
	if(mousestat()==3)
	{
		if(selected(1,0)==2 || selected(1,0)==3)
		{

			for(int loopx=0;loopx<maxx;loopx++)
			{
				for(int loopy=0;loopy<maxy;loopy++)
				{
					x1=windows[3].x1+4+(loopx*size);
					x2=x1+size-1;
					y1=windows[3].y1+17+(loopy*size);
					y2=y1+size-1;
					if(x>=x1 && x<x2 && y>=y1 && y<y2)
					{
						sx=loopx;
						sy=loopy;
					}

				}
			}


		}
		if(selected(1,0)==1)
		{
			for(int loopx=0;loopx<maxx;loopx++)
			{
				for(int loopy=0;loopy<maxy;loopy++)
				{
					x1=windows[3].x1+4+(loopx*size);
					x2=x1+size-1;
					y1=windows[3].y1+17+(loopy*size);
					y2=y1+size-1;
					if(x>=x1 && x<x2 && y>=y1 && y<y2)
					{
						fillit(loopx,loopy,graph[loopx][loopy],selected(0,0));
						drawgrid();
					}
				}
			}
		}
	}
	if(mousestat()==4 && select==1)
	{
		if(selected(1,0)==2)
		{
			for(int loopx=0;loopx<maxx;loopx++)
			{
				for(int loopy=0;loopy<maxy;loopy++)
				{
					x1=windows[3].x1+4+(loopx*size);
					x2=x1+size-1;
					y1=windows[3].y1+17+(loopy*size);
					y2=y1+size-1;
					if(x>=x1 && x<x2 && y>=y1 && y<y2)
					{
						ex=loopx;
						ey=loopy;
						makeline(sx,sy,ex,ey);
						drawgrid();
					}
				}
			}
		}
		if(selected(1,0)==3)
		{
			for(int loopx=0;loopx<maxx;loopx++)
			{
				for(int loopy=0;loopy<maxy;loopy++)
				{
					x1=windows[3].x1+4+(loopx*size);
					x2=x1+size-1;
					y1=windows[3].y1+17+(loopy*size);
					y2=y1+size-1;
					if(x>=x1 && x<x2 && y>=y1 && y<y2)
					{
						ex=loopx;
						ey=loopy;
						rect(sx,sy,ex,ey);
						drawgrid();
					}
				}
			}
		}
	}
}
}
Ejemplo n.º 20
0
void LocalImageLoaderPrivate::prepareImages() {
	QString file, filename, mime;
    int32 filesize = 0;
	QImage img;
	QByteArray data;
	PeerId peer;
    uint64 id, jpeg_id = 0;
	ToPrepareMediaType type;
	{
		QMutexLocker lock(loader->toPrepareMutex());
		ToPrepareMedias &list(loader->toPrepareMedias());
		if (list.isEmpty()) return;

		file = list.front().file;
		img = list.front().img;
		data = list.front().data;
		peer = list.front().peer;
		id = list.front().id;
		type = list.front().type;
	}

	if (img.isNull()) {
		if (!file.isEmpty()) {
			QFileInfo info(file);
			if (type == ToPrepareAuto) {
				QString lower(file.toLower());
				const QStringList &photoExtensions(cPhotoExtensions());
				for (QStringList::const_iterator i = photoExtensions.cbegin(), e = photoExtensions.cend(); i != e; ++i) {
					if (lower.lastIndexOf(*i) == lower.size() - i->size()) {
						if (info.size() < MaxUploadPhotoSize) {
							type = ToPreparePhoto;
							break;
						}
					}
				}
				if (type == ToPrepareAuto && info.size() < MaxUploadDocumentSize) {
					type = ToPrepareDocument;
				}
			}
			if (type != ToPrepareAuto && info.size() < MaxUploadPhotoSize) {
				img = App::readImage(file);
			}
			if (type == ToPrepareDocument) {
				mime = QMimeDatabase().mimeTypeForFile(info).name();
			}
			filename = info.fileName();
			filesize = info.size();
		} else if (!data.isEmpty()) {
			img = App::readImage(data);
			if (type == ToPrepareAuto) {
				if (!img.isNull() && data.size() < MaxUploadPhotoSize) {
					type = ToPreparePhoto;
				} else if (data.size() < MaxUploadDocumentSize) {
					type = ToPrepareDocument;
				} else {
					img = QImage();
				}
			}
			QMimeType mimeType = QMimeDatabase().mimeTypeForData(data);
			if (type == ToPrepareDocument) {
				mime = mimeType.name();
			}
			filename = qsl("Document");
			QStringList patterns = mimeType.globPatterns();
			if (!patterns.isEmpty()) {
				filename = patterns.front().replace('*', filename);
			}
			filesize = data.size();
		}
	} else {
		if (type == ToPrepareDocument) {
			filename = filedialogDefaultName(qsl("image"), qsl(".png"), QString(), true);
			QMimeType mimeType = QMimeDatabase().mimeTypeForName("image/png");
			data = QByteArray();
			{
				QBuffer b(&data);
				img.save(&b, "PNG");
			}
			filesize = data.size();
		} else {
			type = ToPreparePhoto; // only photo from QImage
			filename = qsl("Untitled.jpg");
			filesize = 0;
		}
	}

	if ((img.isNull() && (type != ToPrepareDocument || !filesize)) || type == ToPrepareAuto || (img.isNull() && file.isEmpty() && data.isEmpty())) { // if could not decide what type
		{
			QMutexLocker lock(loader->toPrepareMutex());
			ToPrepareMedias &list(loader->toPrepareMedias());
			list.pop_front();
		}

		QTimer::singleShot(1, this, SLOT(prepareImages()));

		emit imageFailed(id);
	} else {
		PreparedPhotoThumbs photoThumbs;
		QVector<MTPPhotoSize> photoSizes;

		MTPPhotoSize thumb(MTP_photoSizeEmpty(MTP_string("")));
		MTPPhoto photo(MTP_photoEmpty(MTP_long(0)));
		MTPDocument document(MTP_documentEmpty(MTP_long(0)));

		QByteArray jpeg;
		if (type == ToPreparePhoto) {
			int32 w = img.width(), h = img.height();

			QPixmap thumb = (w > 100 || h > 100) ? QPixmap::fromImage(img.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(img);
			photoThumbs.insert('s', thumb);
			photoSizes.push_back(MTP_photoSize(MTP_string("s"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0)));

			QPixmap medium = (w > 320 || h > 320) ? QPixmap::fromImage(img.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(img);
			photoThumbs.insert('m', medium);
			photoSizes.push_back(MTP_photoSize(MTP_string("m"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0)));

			QPixmap full = (w > 800 || h > 800) ? QPixmap::fromImage(img.scaled(800, 800, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(img);
			photoThumbs.insert('x', full);
			photoSizes.push_back(MTP_photoSize(MTP_string("x"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0)));

			{
				QBuffer jpegBuffer(&jpeg);
				full.save(&jpegBuffer, "JPG", 87);
			}
			if (!filesize) filesize = jpeg.size();
		
			photo = MTP_photo(MTP_long(id), MTP_long(0), MTP_int(user), MTP_int(unixtime()), MTP_string(""), MTP_geoPointEmpty(), MTP_vector<MTPPhotoSize>(photoSizes));

			jpeg_id = id;
		} else if ((type == ToPrepareVideo || type == ToPrepareDocument) && !img.isNull()) {
			int32 w = img.width(), h = img.height();

			QPixmap full = (w > 90 || h > 90) ? QPixmap::fromImage(img.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(img);

			{
				QBuffer jpegBuffer(&jpeg);
				full.save(&jpegBuffer, "JPG", 87);
			}

			photoThumbs.insert('0', full);
			thumb = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0));

			jpeg_id = MTP::nonce<uint64>();
		}

		if (type == ToPrepareDocument) {
			document = MTP_document(MTP_long(id), MTP_long(0), MTP_int(MTP::authedId()), MTP_int(unixtime()), MTP_string(filename), MTP_string(mime), MTP_int(filesize), thumb, MTP_int(MTP::maindc()));
		}

		{
			QMutexLocker lock(loader->readyMutex());
			loader->readyList().push_back(ReadyLocalMedia(type, file, filename, filesize, data, id, jpeg_id, peer, photo, photoThumbs, document, jpeg));
		}

		{
			QMutexLocker lock(loader->toPrepareMutex());
			ToPrepareMedias &list(loader->toPrepareMedias());
			list.pop_front();
		}

		QTimer::singleShot(1, this, SLOT(prepareImages()));

		emit imageReady();
	}
}
Ejemplo n.º 21
0
static void SubstrateHookFunctionThumb(SubstrateProcessRef process, void *symbol, void *replace, void **result) {
    if (symbol == NULL)
        return;

    uint16_t *area(reinterpret_cast<uint16_t *>(symbol));

    unsigned align((reinterpret_cast<uintptr_t>(area) & 0x2) == 0 ? 0 : 1);
    uint16_t *thumb(area + align);

    uint32_t *arm(reinterpret_cast<uint32_t *>(thumb + 2));
    uint16_t *trail(reinterpret_cast<uint16_t *>(arm + 2));

    if (
        (align == 0 || area[0] == T$nop) &&
        thumb[0] == T$bx(A$pc) &&
        thumb[1] == T$nop &&
        arm[0] == A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8)
    ) {
        if (result != NULL)
            *result = reinterpret_cast<void *>(arm[1]);

        SubstrateHookMemory code(process, arm + 1, sizeof(uint32_t) * 1);

        arm[1] = reinterpret_cast<uint32_t>(replace);

        return;
    }

    size_t required((trail - area) * sizeof(uint16_t));

    size_t used(0);
    while (used < required)
        used += MSGetInstructionWidthThumb(reinterpret_cast<uint8_t *>(area) + used);
    used = (used + sizeof(uint16_t) - 1) / sizeof(uint16_t) * sizeof(uint16_t);

    size_t blank((used - required) / sizeof(uint16_t));

    uint16_t backup[used / sizeof(uint16_t)];
    memcpy(backup, area, used);

    if (MSDebug) {
        char name[16];
        sprintf(name, "%p", area);
        MSLogHexEx(area, used + sizeof(uint16_t), 2, name);
    }

    if (result != NULL) {

    size_t length(used);
    for (unsigned offset(0); offset != used / sizeof(uint16_t); ++offset)
        if (T$pcrel$ldr(backup[offset]))
            length += 3 * sizeof(uint16_t);
        else if (T$pcrel$b(backup[offset]))
            length += 6 * sizeof(uint16_t);
        else if (T2$pcrel$b(backup + offset)) {
            length += 5 * sizeof(uint16_t);
            ++offset;
        } else if (T$pcrel$bl(backup + offset)) {
            length += 5 * sizeof(uint16_t);
            ++offset;
        } else if (T$pcrel$cbz(backup[offset])) {
            length += 16 * sizeof(uint16_t);
        } else if (T$pcrel$ldrw(backup[offset])) {
            length += 4 * sizeof(uint16_t);
            ++offset;
        } else if (T$pcrel$add(backup[offset]))
            length += 6 * sizeof(uint16_t);
        else if (T$32bit$i(backup[offset]))
            ++offset;

    unsigned pad((length & 0x2) == 0 ? 0 : 1);
    length += (pad + 2) * sizeof(uint16_t) + 2 * sizeof(uint32_t);

    uint16_t *buffer(reinterpret_cast<uint16_t *>(mmap(
        NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0
    )));

    if (buffer == MAP_FAILED) {
        MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno);
        *result = NULL;
        return;
    }

    if (false) fail: {
        munmap(buffer, length);
        *result = NULL;
        return;
    }

    size_t start(pad), end(length / sizeof(uint16_t));
    uint32_t *trailer(reinterpret_cast<uint32_t *>(buffer + end));
    for (unsigned offset(0); offset != used / sizeof(uint16_t); ++offset) {
        if (T$pcrel$ldr(backup[offset])) {
            union {
                uint16_t value;

                struct {
                    uint16_t immediate : 8;
                    uint16_t rd : 3;
                    uint16_t : 5;
                };
            } bits = {backup[offset+0]};

            buffer[start+0] = T$ldr_rd_$pc_im_4$(bits.rd, T$Label(start+0, end-2) / 4);
            buffer[start+1] = T$ldr_rd_$rn_im_4$(bits.rd, bits.rd, 0);

            // XXX: this code "works", but is "wrong": the mechanism is more complex than this
            *--trailer = ((reinterpret_cast<uint32_t>(area + offset) + 4) & ~0x2) + bits.immediate * 4;

            start += 2;
            end -= 2;
        } else if (T$pcrel$b(backup[offset])) {
            union {
                uint16_t value;

                struct {
                    uint16_t imm8 : 8;
                    uint16_t cond : 4;
                    uint16_t /*1101*/ : 4;
                };
            } bits = {backup[offset+0]};

            intptr_t jump(bits.imm8 << 1);
            jump |= 1;
            jump <<= 23;
            jump >>= 23;

            buffer[start+0] = T$b$_$im(bits.cond, (end-6 - (start+0)) * 2 - 4);

            *--trailer = reinterpret_cast<uint32_t>(area + offset) + 4 + jump;
            *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8);
            *--trailer = T$nop << 16 | T$bx(A$pc);

            start += 1;
            end -= 6;
        } else if (T2$pcrel$b(backup + offset)) {
            union {
                uint16_t value;

                struct {
                    uint16_t imm6 : 6;
                    uint16_t cond : 4;
                    uint16_t s : 1;
                    uint16_t : 5;
                };
            } bits = {backup[offset+0]};

            union {
                uint16_t value;

                struct {
                    uint16_t imm11 : 11;
                    uint16_t j2 : 1;
                    uint16_t a : 1;
                    uint16_t j1 : 1;
                    uint16_t : 2;
                };
            } exts = {backup[offset+1]};

            intptr_t jump(1);
            jump |= exts.imm11 << 1;
            jump |= bits.imm6 << 12;

            if (exts.a) {
                jump |= bits.s << 24;
                jump |= (~(bits.s ^ exts.j1) & 0x1) << 23;
                jump |= (~(bits.s ^ exts.j2) & 0x1) << 22;
                jump |= bits.cond << 18;
                jump <<= 7;
                jump >>= 7;
            } else {
Ejemplo n.º 22
0
void LocalImageLoaderPrivate::prepareImages() {
	QString file, filename, mime, stickerMime = qsl("image/webp");
    int32 filesize = 0;
	QImage img;
	QByteArray data;
	PeerId peer;
    uint64 id, thumbId = 0;
	int32 duration = 0;
	QString thumbExt = "jpg";
	ToPrepareMediaType type;
	bool animated = false;
	bool ctrlShiftEnter = false;
	MsgId replyTo = 0;
	{
		QMutexLocker lock(loader->toPrepareMutex());
		ToPrepareMedias &list(loader->toPrepareMedias());
		if (list.isEmpty()) return;

		file = list.front().file;
		img = list.front().img;
		data = list.front().data;
		peer = list.front().peer;
		id = list.front().id;
		type = list.front().type;
		duration = list.front().duration;
		ctrlShiftEnter = list.front().ctrlShiftEnter;
		replyTo = list.front().replyTo;
	}

	if (img.isNull()) {
		if (!file.isEmpty()) {
			QFileInfo info(file);
			if (type == ToPrepareAuto) {
				QString lower(file.toLower());
				const QStringList &photoExtensions(cPhotoExtensions());
				for (QStringList::const_iterator i = photoExtensions.cbegin(), e = photoExtensions.cend(); i != e; ++i) {
					if (lower.lastIndexOf(*i) == lower.size() - i->size()) {
						if (info.size() < MaxUploadPhotoSize) {
							type = ToPreparePhoto;
							break;
						}
					}
				}
				if (type == ToPrepareAuto && info.size() < MaxUploadDocumentSize) {
					type = ToPrepareDocument;
				}
			}
			if (type == ToPrepareDocument) {
				mime = mimeTypeForFile(info).name();
			}
			if (type != ToPrepareAuto && info.size() < MaxUploadPhotoSize) {
				bool opaque = (mime != stickerMime);
				img = App::readImage(file, 0, opaque, &animated);
			}
			filename = info.fileName();
			filesize = info.size();
		} else if (!data.isEmpty()) {
			if (type != ToPrepareAudio) {
				img = App::readImage(data, 0, true, &animated);
				if (type == ToPrepareAuto) {
					if (!img.isNull() && data.size() < MaxUploadPhotoSize) {
						type = ToPreparePhoto;
					} else if (data.size() < MaxUploadDocumentSize) {
						type = ToPrepareDocument;
					} else {
						img = QImage();
					}
				}
			}
			MimeType mimeType = mimeTypeForData(data);
			if (type == ToPrepareDocument || type == ToPrepareAudio) {
				mime = mimeType.name();
			}
			if (mime == "image/jpeg") {
				filename = filedialogDefaultName(qsl("image"), qsl(".jpg"), QString(), true);
			} else if (type == ToPrepareAudio) {
				filename = filedialogDefaultName(qsl("audio"), qsl(".ogg"), QString(), true);
				mime = "audio/ogg";
			} else {
				QString ext;
				QStringList patterns = mimeType.globPatterns();
				if (!patterns.isEmpty()) {
					ext = patterns.front().replace('*', QString());
				}
				filename = filedialogDefaultName((type == ToPrepareAudio) ? qsl("audio") : qsl("doc"), ext, QString(), true);
			}
			filesize = data.size();
		}
	} else {
		if (type == ToPrepareDocument) {
			filename = filedialogDefaultName(qsl("image"), qsl(".png"), QString(), true);
			mime = mimeTypeForName("image/png").name();
			data = QByteArray();
			{
				QBuffer b(&data);
				img.save(&b, "PNG");
			}
			filesize = data.size();
		} else {
			if (img.hasAlphaChannel()) {
				QImage solid(img.width(), img.height(), QImage::Format_ARGB32_Premultiplied);
				solid.fill(st::white->c);
				{
					QPainter(&solid).drawImage(0, 0, img);
				}
				img = solid;
			}
			type = ToPreparePhoto;
			filename = qsl("Untitled.jpg");
			filesize = 0;
		}
	}

	if ((img.isNull() && ((type != ToPrepareDocument && type != ToPrepareAudio) || !filesize)) || type == ToPrepareAuto || (img.isNull() && file.isEmpty() && data.isEmpty())) { // if could not decide what type
		{
			QMutexLocker lock(loader->toPrepareMutex());
			ToPrepareMedias &list(loader->toPrepareMedias());
			list.pop_front();
		}

		QTimer::singleShot(1, this, SLOT(prepareImages()));

		emit imageFailed(id);
	} else {
		PreparedPhotoThumbs photoThumbs;
		QVector<MTPPhotoSize> photoSizes;

		QVector<MTPDocumentAttribute> attributes(1, MTP_documentAttributeFilename(MTP_string(filename)));

		MTPPhotoSize thumb(MTP_photoSizeEmpty(MTP_string("")));
		MTPPhoto photo(MTP_photoEmpty(MTP_long(0)));
		MTPDocument document(MTP_documentEmpty(MTP_long(0)));
		MTPAudio audio(MTP_audioEmpty(MTP_long(0)));

		QByteArray jpeg;
		if (type == ToPreparePhoto) {
			int32 w = img.width(), h = img.height();

			QPixmap thumb = (w > 100 || h > 100) ? QPixmap::fromImage(img.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(img);
			photoThumbs.insert('s', thumb);
			photoSizes.push_back(MTP_photoSize(MTP_string("s"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0)));

			QPixmap medium = (w > 320 || h > 320) ? QPixmap::fromImage(img.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(img);
			photoThumbs.insert('m', medium);
			photoSizes.push_back(MTP_photoSize(MTP_string("m"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0)));

			QPixmap full = (w > 1280 || h > 1280) ? QPixmap::fromImage(img.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(img);
			photoThumbs.insert('y', full);
			photoSizes.push_back(MTP_photoSize(MTP_string("y"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0)));

			{
				QBuffer jpegBuffer(&jpeg);
				full.save(&jpegBuffer, "JPG", 77);
			}
			if (!filesize) filesize = jpeg.size();
		
			photo = MTP_photo(MTP_long(id), MTP_long(0), MTP_int(user), MTP_int(unixtime()), MTP_geoPointEmpty(), MTP_vector<MTPPhotoSize>(photoSizes));

			thumbId = id;
		} else if ((type == ToPrepareVideo || type == ToPrepareDocument) && !img.isNull()) {
			int32 w = img.width(), h = img.height();
			QByteArray thumbFormat = "JPG";
			int32 thumbQuality = 87;
			if (animated) {
				attributes.push_back(MTP_documentAttributeAnimated());
			} else if (mime == stickerMime && w > 0 && h > 0 && w <= StickerMaxSize && h <= StickerMaxSize && filesize < StickerInMemory) {
				attributes.push_back(MTP_documentAttributeSticker(MTP_string(""), MTP_inputStickerSetEmpty()));
				thumbFormat = "webp";
				thumbExt = qsl("webp");
			}
			attributes.push_back(MTP_documentAttributeImageSize(MTP_int(w), MTP_int(h)));
			if (w < 20 * h && h < 20 * w) {
				QPixmap full = (w > 90 || h > 90) ? QPixmap::fromImage(img.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(img, Qt::ColorOnly);

				{
					QBuffer jpegBuffer(&jpeg);
					full.save(&jpegBuffer, thumbFormat, thumbQuality);
				}

				photoThumbs.insert('0', full);
				thumb = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0));

				thumbId = MTP::nonce<uint64>();
			}
		}

		if (type == ToPrepareDocument) {
			document = MTP_document(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_string(mime), MTP_int(filesize), thumb, MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes));
		} else if (type == ToPrepareAudio) {
			audio = MTP_audio(MTP_long(id), MTP_long(0), MTP_int(user), MTP_int(unixtime()), MTP_int(duration), MTP_string(mime), MTP_int(filesize), MTP_int(MTP::maindc()));
		}

		{
			QMutexLocker lock(loader->readyMutex());
			loader->readyList().push_back(ReadyLocalMedia(type, file, filename, filesize, data, id, thumbId, thumbExt, peer, photo, audio, photoThumbs, document, jpeg, ctrlShiftEnter, replyTo));
		}

		{
			QMutexLocker lock(loader->toPrepareMutex());
			ToPrepareMedias &list(loader->toPrepareMedias());
			list.pop_front();
		}

		QTimer::singleShot(1, this, SLOT(prepareImages()));

		emit imageReady();
	}
}
Ejemplo n.º 23
0
void SliderThumb::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    // Halo

    QBrush brush;
    brush.setStyle(Qt::SolidPattern);
    brush.setColor(_haloColor);
    painter.setBrush(brush);
    painter.setPen(Qt::NoPen);

    painter.setRenderHint(QPainter::Antialiasing);

    QPointF disp = Qt::Horizontal == slider->orientation()
        ? QPointF(SLIDER_MARGIN + slider->thumbOffset(), slider->height()/2)
        : QPointF(slider->width()/2, SLIDER_MARGIN + slider->thumbOffset());

    QRectF halo((slider->pos() - QPointF(_haloSize, _haloSize)/2) + disp,
                QSizeF(_haloSize, _haloSize));

    painter.drawEllipse(halo);

    // Knob

    brush.setColor(slider->value() > slider->minimum()
       ? (slider->isEnabled()
          ? _fillColor : Style::instance().themeColor("disabled"))
       : _minFillColor);
    painter.setBrush(brush);

    if (_borderWidth > 0) {
        QPen pen;
        pen.setColor(Style::instance().themeColor("accent3"));
        pen.setWidthF(_borderWidth);
        painter.setPen(pen);
    } else {
        painter.setPen(Qt::NoPen);
    }

    QRectF geometry = Qt::Horizontal == slider->orientation()
        ? QRectF(slider->thumbOffset(), slider->height()/2 - SLIDER_MARGIN,
                 SLIDER_MARGIN*2, SLIDER_MARGIN*2).translated(slider->pos())
        : QRectF(slider->width()/2 - SLIDER_MARGIN, slider->thumbOffset(),
                 SLIDER_MARGIN*2, SLIDER_MARGIN*2).translated(slider->pos());

    QRectF thumb(0, 0, _diameter, _diameter);

    thumb.moveCenter(geometry.center());

    painter.drawEllipse(thumb);

#ifdef DEBUG_LAYOUT
    QPen pen;
    pen.setColor(Qt::red);
    pen.setWidth(2);
    painter.setPen(pen);
    painter.setBrush(Qt::NoBrush);

    painter.drawRect(geometry);

    painter.drawRect(rect().adjusted(0, 0, -2, -2));
#endif

    QWidget::paintEvent(event);
}