#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); }