Blob Blame Raw


#include "toonz/glrasterpainter.h"
#include "tgl.h"
#include "texturemanager.h"
#include "tpalette.h"
#include "tropcm.h"
#include "tvectorimage.h"
#include "tvectorrenderdata.h"
#include "tvectorgl.h"

namespace
{

void doDrawRaster(const TAffine &aff,
				  UCHAR *buffer, int wrap, int bpp, const TDimension &rasDim,
				  const TRect &bbox,
				  bool showBBox,
				  GLenum magFilter,
				  GLenum minFilter,
				  bool premultiplied)
{
	if (!buffer)
		return;

	bool isRGBM = (bpp == 4);

	if (!isRGBM) {
		if (bpp != 1)
			return;
	}

	TDimension maxSize = TextureManager::instance()->getMaxSize(isRGBM);

	if (bbox.getLx() > maxSize.lx) {
		TRect leftBox(bbox.getP00(), TDimension(maxSize.lx, bbox.getLy()));
		TRect rightBox(TPoint(bbox.getP00().x + maxSize.lx, bbox.getP00().y), bbox.getP11());

		assert(leftBox.getLx() == maxSize.lx);
		assert(rightBox.getLx() == bbox.getLx() - maxSize.lx);
		assert(leftBox.getLy() == bbox.getLy());
		assert(rightBox.getLy() == bbox.getLy());

		doDrawRaster(aff, buffer, wrap, bpp, rasDim, leftBox, showBBox, magFilter, minFilter, premultiplied);
		doDrawRaster(aff, buffer, wrap, bpp, rasDim, rightBox, showBBox, magFilter, minFilter, premultiplied);
		return;
	}

	if (bbox.getLy() > maxSize.ly) {
		TRect bottomBox(bbox.getP00(), TDimension(bbox.getLx(), maxSize.ly));
		TRect topBox(TPointI(bbox.getP00().x, bbox.getP00().y + maxSize.ly), bbox.getP11());

		assert(bottomBox.getLy() == maxSize.ly);
		assert(topBox.getLy() == bbox.getLy() - maxSize.ly);
		assert(bottomBox.getLx() == bbox.getLx());
		assert(topBox.getLx() == bbox.getLx());

		doDrawRaster(aff, buffer, wrap, bpp, rasDim, bottomBox, showBBox, magFilter, minFilter, premultiplied);
		doDrawRaster(aff, buffer, wrap, bpp, rasDim, topBox, showBBox, magFilter, minFilter, premultiplied);

		return;
	}

	glPushMatrix();
	TTranslation T((bbox.getP00().x - (rasDim.lx - bbox.getLx()) / 2.),
				   (bbox.getP00().y - (rasDim.ly - bbox.getLy()) / 2.));
	tglMultMatrix(aff * T);

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);

	glTexEnvf(GL_TEXTURE_ENV,
			  GL_TEXTURE_ENV_MODE,
			  GL_REPLACE);

	glEnable(GL_TEXTURE_2D);
	glEnable(GL_BLEND);

	if (premultiplied)
		glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
	else
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	TDimension ts = TextureManager::instance()->selectTexture(bbox.getSize(), isRGBM);

	GLenum fmt, type;
	TextureManager::instance()->getFmtAndType(isRGBM, fmt, type);

	int width = bbox.getLx();
	int height = bbox.getLy();
	int y = bbox.getP00().y;
	int x = bbox.getP00().x;
	buffer += (x + y * wrap) * bpp;

	glPixelStorei(GL_UNPACK_ROW_LENGTH, wrap);

	glTexSubImage2D(
		GL_TEXTURE_2D, // target (is a 2D texture)
		0,			   // is one level only
		0,
		0,
		width,
		height,
		fmt,
		type,
		buffer);
	CHECK_ERRORS_BY_GL

	double halfWidth = 0.5 * bbox.getLx();
	double halfHeight = 0.5 * bbox.getLy();

	TPointD v0((-halfWidth), (-halfHeight));
	TPointD v1((halfWidth), (-halfHeight));
	TPointD v2((-halfWidth), (halfHeight));
	TPointD v3((halfWidth), (halfHeight));

	double s = (bbox.getLx()) / (double)ts.lx;
	double t = (bbox.getLy()) / (double)ts.ly;

	glColor3d(0, 0, 0);
	glBegin(GL_QUAD_STRIP);
	glTexCoord2d(0, 0);
	glVertex2d(v0.x, v0.y);
	glTexCoord2d(s, 0);
	glVertex2d(v1.x, v1.y);
	glTexCoord2d(0, t);
	glVertex2d(v2.x, v2.y);
	glTexCoord2d(s, t);
	glVertex2d(v3.x, v3.y);
	glEnd();

	glDisable(GL_BLEND);
	glDisable(GL_TEXTURE_2D);

	if (showBBox) {
		glBegin(GL_LINE_LOOP);
		glVertex2d(v0.x, v0.y);
		glVertex2d(v1.x, v1.y);
		glVertex2d(v3.x, v3.y);
		glVertex2d(v2.x, v2.y);
		glEnd();
	}
	glPopMatrix();
}

//----------------------------------------------------------------------------
void doDrawRaster(const TAffine &aff,
				  const TRasterImageP &ri,
				  const TRectI &bbox,
				  bool showBBox,
				  GLenum magFilter,
				  GLenum minFilter,
				  bool premultiplied)
{
	TRasterP r = ri->getRaster();
	r->lock();
	doDrawRaster(aff,
				 r->getRawData(), r->getWrap(), r->getPixelSize(),
				 r->getSize(),
				 bbox,
				 showBBox,
				 magFilter,
				 minFilter,
				 premultiplied);
	r->unlock();
}

} //namespace

//===================================================================

void GLRasterPainter::drawRaster(const TAffine &aff, UCHAR *buffer, int wrap, int bpp, const TDimension &rasSize, bool premultiplied)
{
	if (!buffer)
		return;

	doDrawRaster(
		aff, buffer, wrap, bpp, rasSize, rasSize,
		false, GL_NEAREST, GL_LINEAR, premultiplied);
}

//----------------------------------------------------------------------------

void GLRasterPainter::drawRaster(const TAffine &aff, const TRasterImageP &ri, bool premultiplied)
{
	if (!ri || !ri->getRaster())
		return;

	doDrawRaster(
		aff, ri, ri->getRaster()->getBounds(),
		false, GL_NEAREST, GL_LINEAR, premultiplied);
}

//----------------------------------------------------------------------------

void GLRasterPainter::drawRaster(const TAffine &aff, const TToonzImageP &ti, bool showSavebox)
{
	TRect saveBox = ti->getSavebox();
	if (saveBox.isEmpty())
		return;

	TRasterCM32P ras = ti->getRaster();
	TPaletteP palette = ti->getPalette();
	TRaster32P ras32(ras->getSize());

	TRop::convert(ras32, ras, palette, saveBox);

	TRasterImageP rasImg(ras32);
	double dpix, dpiy;
	ti->getDpi(dpix, dpiy);
	rasImg->setDpi(dpix, dpiy);

	bool premultiplied = true;
	doDrawRaster(aff, rasImg, saveBox, showSavebox, GL_NEAREST, GL_LINEAR, premultiplied);
}