| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| namespace |
| { |
| |
| TRandom Random; |
| |
| |
| |
| typedef std::pair<TPointD, TPointD> PointPair; |
| typedef std::vector<TPointD> PointArray; |
| |
| PointPair computeTexParameters(const TPointD &p1, |
| const TPointD &p2, |
| const TPointD &tex1, |
| const TPointD &tex2, |
| const PointPair &newP, |
| const TDimension &size) |
| { |
| |
| static PointPair tex; |
| |
| |
| TPointD v = (newP.first + newP.second) * 0.5 - (p2 + p1) * 0.5; |
| |
| |
| double lenghtNextP1NextP2 = tdistance(newP.first, newP.second); |
| |
| |
| double texParameterOffset = lenghtNextP1NextP2 / size.lx * 0.5; |
| |
| |
| tex.first.x = 0.5 - texParameterOffset; |
| tex.second.x = 0.5 + texParameterOffset; |
| |
| |
| double disty = norm(v); |
| assert(tex1.y == tex2.y); |
| |
| |
| texParameterOffset = disty / size.ly; |
| |
| |
| tex.first.y = |
| tex.second.y = tex1.y + texParameterOffset; |
| |
| return tex; |
| } |
| |
| |
| |
| void setTexCoords(const TPointD tex, TOutlinePoint &p) |
| { |
| p.u = tex.x; |
| p.v = tex.y; |
| } |
| |
| |
| |
| TPointD getTexCoords(const TOutlinePoint &p) |
| { |
| return TPointD(p.u, p.v); |
| } |
| |
| } |
| |
| |
| TTextureStyle::TTextureStyle(const TRasterP &ras, const TFilePath &texturePath) |
| : m_texture(ras), m_texturePath(texturePath), m_tessellator(new TglTessellator), m_params(), m_texturePathLoaded() |
| { |
| setAverageColor(); |
| } |
| |
| |
| |
| TFilePath TImageStyle::m_libraryDir; |
| ToonzScene *TImageStyle::m_currentScene = 0; |
| |
| |
| |
| TTextureStyle::TTextureStyle(const TTextureStyle &other) |
| : TOutlineStyle(other), TRasterStyleFx(other), TImageStyle(other), m_texture(other.m_texture), m_texturePath(other.m_texturePath), m_texturePathLoaded(other.m_texturePathLoaded), m_params(other.m_params), m_tessellator(new TglTessellator) |
| { |
| setAverageColor(); |
| } |
| |
| |
| |
| TTextureStyle::~TTextureStyle() |
| { |
| delete m_tessellator; |
| } |
| |
| |
| |
| TColorStyle *TTextureStyle::clone() const |
| { |
| return new TTextureStyle(*this); |
| } |
| |
| |
| |
| QString TTextureStyle::getDescription() const |
| { |
| return "TextureStyle"; |
| } |
| |
| |
| |
| |
| int TTextureStyle::getTagId() const |
| { |
| return 4; |
| } |
| |
| |
| TRasterP TTextureStyle::getTexture() const |
| { |
| return m_texture; |
| } |
| |
| |
| void TTextureStyle::setAverageColor() |
| { |
| loadTextureRaster(); |
| |
| TRaster32P r32 = (TRaster32P)m_texture; |
| if (!r32) { |
| m_averageColor = TPixel::Black; |
| return; |
| } |
| if (m_params.m_isPattern) { |
| m_averageColor = m_params.m_patternColor; |
| return; |
| } |
| TPixelD color(0, 0, 0, 0); |
| r32->lock(); |
| for (int i = 0; i < r32->getLy(); i++) { |
| TPixel32 *buf = r32->pixels(i); |
| for (int j = 0; j < r32->getLx(); j++, buf++) { |
| color.r += buf->r; |
| color.g += buf->g; |
| color.b += buf->b; |
| color.m += buf->m; |
| } |
| } |
| r32->unlock(); |
| int pixels = r32->getLx() * r32->getLy(); |
| m_averageColor.r = (int)(color.r / pixels); |
| m_averageColor.g = (int)(color.g / pixels); |
| m_averageColor.b = (int)(color.b / pixels); |
| m_averageColor.m = (int)(color.m / pixels); |
| } |
| |
| void TTextureStyle::setTexture(const TRasterP &ras) |
| { |
| m_texture = ras; |
| delete m_tessellator; |
| m_tessellator = new TglTessellator; |
| |
| setAverageColor(); |
| } |
| |
| TPixel32 TTextureStyle::getAverageColor() const |
| { |
| return m_averageColor; |
| } |
| |
| |
| void TTextureStyle::computeOutline(const TStroke *stroke, |
| TStrokeOutline &outline, |
| TOutlineUtil::OutlineParameter param) const |
| { |
| TOutlineStyle::computeOutline(stroke, outline, param); |
| vector<TOutlinePoint> &v = outline.getArray(); |
| PointPair newPnt; |
| TDimension size = m_texture->getSize(); |
| UINT i = 0; |
| for (i = 2; i < v.size(); i += 2) { |
| newPnt.first = convert(v[i]); |
| newPnt.second = convert(v[i + 1]); |
| newPnt = computeTexParameters(convert(v[i - 2]), convert(v[i - 1]), |
| getTexCoords(v[i - 2]), getTexCoords(v[i - 1]), |
| newPnt, |
| size); |
| setTexCoords(newPnt.first, v[i]); |
| setTexCoords(newPnt.second, v[i + 1]); |
| } |
| for (i = 0; i < v.size(); i++) { |
| v[i].u = (i & 1) == 0 ? 0 : 1; |
| } |
| } |
| |
| |
| void TTextureStyle::drawStroke(const TColorFunction *cf, TStrokeOutline *outline, const TStroke *stroke) const |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| UINT i; |
| |
| vector<TOutlinePoint> &v = outline->getArray(); |
| if (v.empty()) |
| return; |
| |
| const TRasterP texture = m_texture; |
| |
| assert(!v.empty() || !texture); |
| |
| if (v.empty() || !texture) |
| return; |
| |
| static const int stride = sizeof(TOutlinePoint); |
| |
| glColor4d(1.0, 1.0, 1.0, 1.0); |
| |
| |
| glEnableClientState(GL_VERTEX_ARRAY); |
| glVertexPointer(2, GL_DOUBLE, stride, &v[0]); |
| |
| glEnable(GL_TEXTURE_2D); |
| |
| |
| GLboolean blendEnabled; |
| glGetBooleanv(GL_BLEND, &blendEnabled); |
| assert(blendEnabled); |
| |
| |
| glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
| glTexCoordPointer(2, GL_DOUBLE, stride, &(v[0].u)); |
| |
| TextureInfoForGL texInfo; |
| |
| m_texture->lock(); |
| TRasterP texImage = prepareTexture(m_texture, texInfo); |
| |
| |
| GLuint texId; |
| glGenTextures(1, &texId); |
| |
| glBindTexture(GL_TEXTURE_2D, texId); |
| |
| |
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); |
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); |
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| |
| glTexEnvf(GL_TEXTURE_ENV, |
| GL_TEXTURE_ENV_MODE, |
| GL_MODULATE); |
| |
| glPixelStorei(GL_UNPACK_ROW_LENGTH, |
| texImage->getWrap() != texImage->getLx() ? texImage->getWrap() : 0); |
| |
| if (texImage != m_texture) |
| texImage->lock(); |
| |
| |
| glTexImage2D(GL_TEXTURE_2D, |
| 0, |
| texInfo.internalformat, |
| texInfo.width, |
| texInfo.height, |
| 0, |
| texInfo.type, |
| texInfo.format, |
| texImage->getRawData()); |
| |
| m_texture->unlock(); |
| if (texImage != m_texture) |
| texImage->lock(); |
| |
| |
| glBegin(GL_LINE_STRIP); |
| for (i = 0; i < v.size(); i += 2) |
| glArrayElement(i); |
| glEnd(); |
| glBegin(GL_LINE_STRIP); |
| for (i = 1; i < v.size(); i += 2) |
| glArrayElement(i); |
| glEnd(); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| glDrawArrays(QUAD_PRIMITIVE, 0, v.size()); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| glDeleteTextures(1, &texId); |
| |
| glDisableClientState(GL_VERTEX_ARRAY); |
| glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
| glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); |
| glDisable(GL_TEXTURE_2D); |
| } |
| |
| |
| void TTextureStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const |
| { |
| if (m_tessellator) |
| m_tessellator->tessellate(cf, antiAliasing, boundary, m_texture); |
| } |
| |
| void TTextureStyle::drawRegion(TFlash &flash, const TRegion *r) const |
| { |
| flash.setTexture(m_texture); |
| flash.setFillStyleMatrix(TAffine()); |
| flash.drawRegion(*r); |
| |
| } |
| |
| |
| void TTextureStyle::setFill(TFlash &flash) const |
| { |
| flash.setTexture(getTexture()); |
| } |
| |
| |
| |
| |
| namespace |
| { |
| |
| void tileRaster(const TRaster32P &tile, const TRaster32P &rout) |
| { |
| int x0, y0; |
| |
| if (rout->getLy() > tile->getLy()) |
| y0 = tile->getLy() - (((rout->getLy() - tile->getLy()) / 2) % tile->getLy()); |
| else |
| y0 = (tile->getLy() - rout->getLy()) / 2; |
| if (rout->getLx() > tile->getLx()) |
| x0 = tile->getLx() - (((rout->getLx() - tile->getLx()) / 2) % tile->getLx()); |
| else |
| x0 = (tile->getLx() - rout->getLx()) / 2; |
| |
| |
| |
| while (x0 < 0) |
| x0 += tile->getLx(); |
| while (y0 < 0) |
| y0 += tile->getLy(); |
| x0 = x0 % tile->getLx(); |
| y0 = y0 % tile->getLy(); |
| |
| int y = y0; |
| for (int i = 0; i < rout->getLy(); i++, y++) { |
| if (y == tile->getLy()) |
| y = 0; |
| int x = x0; |
| TPixel32 *pixout = rout->pixels(i); |
| TPixel32 *pixin = tile->pixels(y) + x; |
| |
| for (int j = 0; j < rout->getLx(); j++, pixin++, pixout++, x++) { |
| if (x == tile->getLx()) { |
| x = 0, pixin = tile->pixels(y); |
| } |
| *pixout = *pixin; |
| } |
| } |
| } |
| |
| |
| |
| void doContrast(double contrast, const TRaster32P &rin) |
| { |
| TPixel32 *row, *pix; |
| int i, j, lx, ly, wrap; |
| double line_avg_r, line_avg_g, line_avg_b; |
| double avg_r = 0, avg_g = 0, avg_b = 0; |
| |
| lx = rin->getLx(); |
| ly = rin->getLy(); |
| wrap = rin->getWrap(); |
| |
| for (j = 0, row = (TPixel32 *)rin->getRawData(); j < ly; j++, row += wrap) { |
| line_avg_r = 0; |
| line_avg_g = 0; |
| line_avg_b = 0; |
| for (i = 0, pix = row; i < lx; i++, pix++) { |
| line_avg_r += pix->r; |
| line_avg_g += pix->g; |
| line_avg_b += pix->b; |
| } |
| avg_r += line_avg_r / lx; |
| avg_g += line_avg_g / lx; |
| avg_b += line_avg_b / lx; |
| } |
| |
| avg_r /= ly; |
| avg_g /= ly; |
| avg_b /= ly; |
| |
| int ires; |
| double dres; |
| TPixel32 lut[256]; |
| |
| for (int i = 0; i < 256; i++) { |
| dres = contrast * (i - avg_r) + avg_r; |
| ires = tround(dres); |
| lut[i].r = tcrop(ires, 0, 255); |
| dres = contrast * (i - avg_g) + avg_g; |
| ires = tround(dres); |
| lut[i].g = tcrop(ires, 0, 255); |
| dres = contrast * (i - avg_b) + avg_b; |
| ires = tround(dres); |
| lut[i].b = tcrop(ires, 0, 255); |
| } |
| |
| for (j = 0, row = (TPixel32 *)rin->getRawData(); j < ly; j++, row += wrap) { |
| for (i = 0, pix = row; i < lx; i++, pix++) { |
| pix->r = lut[pix->r].r; |
| pix->g = lut[pix->g].g; |
| pix->b = lut[pix->b].b; |
| |
| if (pix->r > pix->m) |
| pix->r = pix->m; |
| if (pix->g > pix->m) |
| pix->g = pix->m; |
| if (pix->b > pix->m) |
| pix->b = pix->m; |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| static void doPattern(const TRaster32P &r, TPixel32 color) |
| { |
| int i, j, fac = 0; |
| |
| if (TPixelGR8::from(color).value < 128) |
| fac = 255 - color.m * (255.0 - color.m) / 255.0; |
| |
| TPixel32 *buf; |
| UINT b; |
| |
| for (i = 0; i < r->getLy(); i++) { |
| buf = (TPixel32 *)r->pixels(i); |
| for (j = 0; j < r->getLx(); j++, buf++) { |
| if (buf->m > 0) { |
| b = TPixelGR8::from(*buf).value * MAGICFAC; |
| |
| buf->r = BYTE_ROUND(b * color.r + fac); |
| buf->g = BYTE_ROUND(b * color.g + fac); |
| buf->b = BYTE_ROUND(b * color.b + fac); |
| if (buf->m < 255 || color.m < 255) { |
| buf->m = BYTE_ROUND(buf->m * color.m / 255.0); |
| premult(*buf); |
| } else |
| buf->m = 255; |
| } |
| } |
| } |
| } |
| |
| |
| |
| void applyTexture(const TRaster32P &rTex, const TRaster32P &r, TPoint p) |
| { |
| while (p.x < 0) |
| p.x += rTex->getLx(); |
| while (p.y < 0) |
| p.y += rTex->getLy(); |
| r->lock(); |
| rTex->lock(); |
| for (int y = 0, yTex = p.y; y < r->getLy(); y++, yTex++) { |
| TPixel32 *pixIn = r->pixels(y); |
| if (yTex >= rTex->getLy()) |
| yTex -= rTex->getLy(); |
| |
| TPixel32 *pixTex = (TPixel32 *)(rTex->pixels(yTex)) + p.x; |
| |
| for (int x = 0, xTex = p.x; x < r->getLx(); x++, xTex++, pixIn++, pixTex++) { |
| if (xTex >= rTex->getLx()) |
| xTex -= rTex->getLx(), pixTex -= rTex->getLx(); |
| |
| if (pixIn->m == 0) |
| continue; |
| |
| if (pixIn->m == 255) |
| *pixIn = *pixTex; |
| else { |
| pixIn->r = pixIn->m * pixTex->r / 255; |
| pixIn->g = pixIn->m * pixTex->g / 255; |
| pixIn->b = pixIn->m * pixTex->b / 255; |
| pixIn->m = pixIn->m * pixTex->m / 255; |
| } |
| } |
| } |
| r->unlock(); |
| rTex->unlock(); |
| } |
| |
| } |
| |
| |
| TPoint computeCentroid(const TRaster32P &r); |
| |
| |
| |
| int TTextureStyle::getParamCount() const |
| { |
| return 8; |
| } |
| |
| |
| |
| QString TTextureStyle::getParamNames(int index) const |
| { |
| switch (index) { |
| case 0: |
| return "Use As Pattern"; |
| CASE 1 : return "Position"; |
| CASE 2 : return "Scale"; |
| CASE 3 : return "Rotation(degrees)"; |
| CASE 4 : return "X displ"; |
| CASE 5 : return "Y displ"; |
| CASE 6 : return "Contrast"; |
| CASE 7 : return "Load From File"; |
| DEFAULT: |
| assert(false); |
| } |
| |
| return QString(""); |
| } |
| |
| |
| |
| void TTextureStyle::getParamRange(int index, double &min, double &max) const |
| { |
| assert(index > 1); |
| switch (index) { |
| case 2: |
| min = 0.15; |
| max = 10; |
| CASE 3 : min = -180; |
| max = 180; |
| CASE 4 : min = -500; |
| max = 500; |
| CASE 5 : min = -500; |
| max = 500; |
| CASE 6 : min = 0.01; |
| max = 10; |
| DEFAULT: |
| assert(false); |
| } |
| } |
| |
| |
| |
| TColorStyle::ParamType TTextureStyle::getParamType(int index) const |
| { |
| assert(0 <= index && index < getParamCount()); |
| if (index == 0) |
| return TColorStyle::BOOL; |
| else if (index == 1) |
| return TColorStyle::ENUM; |
| else if (index == 7) |
| return TColorStyle::FILEPATH; |
| return TColorStyle::DOUBLE; |
| } |
| |
| |
| |
| void TTextureStyle::getParamRange(int index, QStringList &enumItems) const |
| { |
| assert(index == 1 || index == 7); |
| if (index == 1) |
| enumItems << "FIXED" |
| << "AUTOMATIC" |
| << "RANDOM"; |
| else if (index == 7) |
| enumItems << "bmp" |
| << "jpg" |
| << "png" |
| << "tif" |
| << "tiff" |
| << "gif"; |
| } |
| |
| |
| |
| bool TTextureStyle::getParamValue(TColorStyle::bool_tag, int index) const |
| { |
| assert(index == 0); |
| return m_params.m_isPattern; |
| } |
| |
| |
| |
| double TTextureStyle::getParamValue(TColorStyle::double_tag, int index) const |
| { |
| assert(index > 1); |
| switch (index) { |
| case 2: |
| return m_params.m_scale; |
| CASE 3 : return m_params.m_rotation; |
| CASE 4 : return m_params.m_displacement.x; |
| CASE 5 : return m_params.m_displacement.y; |
| CASE 6 : return m_params.m_contrast; |
| DEFAULT: |
| assert(false); |
| } |
| return 0; |
| } |
| |
| TFilePath TTextureStyle::getParamValue(TColorStyle::TFilePath_tag, int index) const |
| { |
| assert(index == 7); |
| return m_texturePath; |
| } |
| |
| |
| |
| int TTextureStyle::getParamValue(TColorStyle::int_tag, int index) const |
| { |
| assert(index == 1); |
| |
| return m_params.m_type; |
| } |
| |
| |
| |
| void TTextureStyle::setParamValue(int index, const TFilePath &value) |
| { |
| assert(index == 7); |
| m_texturePath = value; |
| setAverageColor(); |
| } |
| |
| |
| |
| void TTextureStyle::setParamValue(int index, int value) |
| { |
| assert(index == 1); |
| |
| m_params.m_type = (TTextureParams::TYPE)value; |
| } |
| |
| |
| |
| void TTextureStyle::setParamValue(int index, bool value) |
| { |
| assert(index == 0); |
| m_params.m_isPattern = value; |
| } |
| |
| |
| |
| void TTextureStyle::setParamValue(int index, double value) |
| { |
| assert(index > 1); |
| switch (index) { |
| case 0: |
| m_params.m_isPattern = (((int)value == 0) ? false : true); |
| CASE 1 : m_params.m_type = (((int)value == 0) ? TTextureParams::FIXED : ((int)value == 1) ? TTextureParams::AUTOMATIC : TTextureParams::RANDOM); |
| |
| CASE 2 : m_params.m_scale = value; |
| CASE 3 : m_params.m_rotation = value; |
| CASE 4 : m_params.m_displacement.x = value; |
| CASE 5 : m_params.m_displacement.y = value; |
| CASE 6 : m_params.m_contrast = value; |
| DEFAULT: |
| assert(false); |
| } |
| } |
| |
| |
| bool TTextureStyle::loadTextureRaster() |
| { |
| if (m_texturePathLoaded != TFilePath() && m_texturePath == m_texturePathLoaded) |
| return true; |
| |
| m_texturePathLoaded = m_texturePath; |
| |
| TFilePath path; |
| if (m_texturePath.getParentDir() != TFilePath()) |
| { |
| assert(m_currentScene); |
| path = m_currentScene->decodeFilePath(m_texturePath); |
| if (path.isLevelName()) { |
| TLevelReader lr(path); |
| path = path.withFrame(lr.loadInfo()->begin()->first); |
| } |
| } else |
| { |
| path = m_texturePath.withParentDir(m_libraryDir + "textures"); |
| } |
| |
| TRasterP aux; |
| |
| if (!TImageReader::load(path, aux)) { |
| m_texture = TRaster32P(128, 128); |
| m_texture->clear(); |
| m_texturePathLoaded = TFilePath(); |
| return false; |
| } |
| |
| m_texture = aux; |
| return true; |
| } |
| |
| |
| TRaster32P TTextureStyle::loadTextureRasterWithFrame(int frame) const |
| { |
| if (m_texturePathLoaded != TFilePath() && m_texturePath == m_texturePathLoaded && (!m_texturePath.isLevelName() || frame == 0)) |
| return m_texture->clone(); |
| |
| TFilePath path; |
| if (m_texturePath.getParentDir() != TFilePath()) |
| { |
| assert(m_currentScene); |
| path = m_currentScene->decodeFilePath(m_texturePath); |
| if (path.isLevelName()) { |
| TLevelReader lr(path); |
| TLevelP info = lr.loadInfo(); |
| TLevel::Iterator it = info->begin(); |
| |
| std::advance(it, frame % (info->getFrameCount())); |
| |
| |
| path = path.withFrame(it->first); |
| } |
| } else |
| { |
| path = m_texturePath.withParentDir(m_libraryDir + "textures"); |
| } |
| |
| TRasterP aux; |
| |
| if (!TImageReader::load(path, aux)) { |
| aux = TRaster32P(128, 128); |
| aux->clear(); |
| } |
| return aux; |
| } |
| |
| |
| |
| void TTextureStyle::loadData(TInputStreamInterface &is) |
| { |
| |
| if (is.versionNumber().first < 71) { |
| is >> m_texture; |
| setTexture(m_texture); |
| return; |
| } |
| |
| string path; |
| is >> path; |
| m_texturePath = TFilePath(path); |
| |
| |
| |
| loadTextureRaster(); |
| |
| is >> m_params.m_patternColor; |
| m_averageColor = m_params.m_patternColor; |
| |
| double value; |
| |
| is >> value; |
| m_params.m_isPattern = value == 1.0 ? true : false; |
| |
| is >> value; |
| m_params.m_type = (((int)value == 0) ? TTextureParams::FIXED : ((int)value == 1) ? TTextureParams::AUTOMATIC : TTextureParams::RANDOM); |
| |
| is >> m_params.m_scale; |
| is >> m_params.m_rotation; |
| is >> m_params.m_displacement.x; |
| is >> m_params.m_displacement.y; |
| is >> m_params.m_contrast; |
| |
| delete m_tessellator; |
| m_tessellator = new TglTessellator; |
| |
| setAverageColor(); |
| } |
| |
| |
| |
| void TTextureStyle::saveData(TOutputStreamInterface &os) const |
| { |
| |
| |
| wstring wstr = m_texturePath.getWideString(); |
| string str; |
| str.assign(wstr.begin(), wstr.end()); |
| os << str; |
| |
| os << m_params.m_patternColor; |
| |
| os << ((double)m_params.m_isPattern); |
| |
| double value = (m_params.m_type == TTextureParams::FIXED) ? 0 : ((m_params.m_type == TTextureParams::AUTOMATIC) ? 1 : 2); |
| os << value; |
| |
| os << m_params.m_scale; |
| os << m_params.m_rotation; |
| os << m_params.m_displacement.x; |
| os << m_params.m_displacement.y; |
| os << m_params.m_contrast; |
| } |
| |
| |
| |
| int TTextureStyle::getColorParamCount() const |
| { |
| return 1; |
| } |
| |
| TPixel32 TTextureStyle::getColorParamValue(int index) const |
| { |
| return m_params.m_patternColor; |
| } |
| |
| void TTextureStyle::setColorParamValue(int index, const TPixel32 &color) |
| { |
| m_params.m_patternColor = color; |
| } |
| |
| inline void drawdot(TPixel32 *pix, int wrap) |
| { |
| for (int i = -wrap; i <= wrap; i += wrap) |
| for (int j = -1; j <= 1; j++) |
| *(pix + i + j) = TPixel::Red; |
| } |
| |
| void TTextureStyle::fillCustomTextureIcon(const TRaster32P &r) |
| { |
| r->fill(TPixel::White); |
| int x1, x2, x3; |
| x2 = r->getLx() / 2; |
| x1 = x2 + ((r->getLx() <= 64) ? 6 : 9); |
| x3 = x2 - ((r->getLx() <= 64) ? 6 : 9); |
| |
| TPixel32 *pix = r->pixels(r->getLy() / 4); |
| drawdot(pix + x1, r->getWrap()); |
| drawdot(pix + x2, r->getWrap()); |
| drawdot(pix + x3, r->getWrap()); |
| |
| |
| |
| |
| } |
| |
| void TTextureStyle::makeIcon(const TDimension &outputRect) |
| { |
| |
| if (!m_icon || m_icon->getSize() != outputRect) { |
| TRaster32P ras(outputRect); |
| ras->fill(TPixel::Red); |
| m_icon = ras; |
| } |
| |
| if (!loadTextureRaster()) { |
| fillCustomTextureIcon(m_icon); |
| |
| return; |
| } |
| TRaster32P rTex; |
| |
| if (m_params.m_contrast != 1.0 || m_params.m_isPattern) { |
| rTex = m_texture->clone(); |
| |
| if (m_params.m_contrast != 1.0) |
| doContrast(m_params.m_contrast, rTex); |
| |
| if (m_params.m_isPattern) |
| doPattern(rTex, m_params.m_patternColor); |
| } else |
| rTex = m_texture; |
| |
| double fitScale = tmin((double)(outputRect.lx) / m_texture->getLx(), (double)(outputRect.ly) / m_texture->getLy()); |
| TAffine affine = TScale(m_params.m_scale * (fitScale)) * TRotation(-m_params.m_rotation); |
| |
| if (affine != TAffine()) { |
| int border = 2; |
| TRaster32P raux(m_icon->getLx() + 2 * border, m_icon->getLy() + 2 * border); |
| TRaster32P rin(convert(affine.inv() * TRectD(0, 0, raux->getLx() - 1, raux->getLy() - 1)).getSize()); |
| tileRaster(rTex, rin); |
| |
| TRop::resample(raux, rin, affine.place(rin->getCenterD(), raux->getCenterD())); |
| |
| TRop::copy(m_icon, raux->extract(border, border, m_icon->getLx() + border - 1, m_icon->getLy() + border - 1)); |
| } else |
| applyTexture(rTex, m_icon, TPoint()); |
| } |
| |
| |
| |
| |
| |
| bool TTextureStyle::doCompute(const Params ¶ms) const |
| { |
| TRaster32P rTex = loadTextureRasterWithFrame(params.m_frame); |
| TRaster32P r = params.m_r; |
| |
| |
| assert(r); |
| |
| if (m_params.m_contrast != 1.0) |
| doContrast(m_params.m_contrast, rTex); |
| |
| if (m_params.m_isPattern) |
| doPattern(rTex, m_params.m_patternColor); |
| |
| TPoint p = -convert(m_params.m_displacement); |
| |
| if (m_params.m_type == TTextureParams::FIXED) |
| p += params.m_p; |
| else if (m_params.m_type == TTextureParams::RANDOM) |
| p += TPoint(Random.getUInt(m_texture->getLx()), Random.getUInt(m_texture->getLy())); |
| |
| if (m_params.m_scale != 1.0 || m_params.m_rotation != 0.0) { |
| TAffine affine = TScale(m_params.m_scale) * TRotation(-m_params.m_rotation); |
| |
| if (m_params.m_type == TTextureParams::AUTOMATIC) { |
| TRect bBox; |
| TRop::computeBBox(r, bBox); |
| |
| r = r->extract(bBox); |
| p += r->getCenter() - computeCentroid(r); |
| } |
| |
| p.x = (p.x % m_texture->getLx()); |
| p.y = (p.y % m_texture->getLy()); |
| |
| TRect rectIn = convert(affine.inv() * TRectD(0, 0, r->getLx() - 1, r->getLy() - 1)); |
| TRaster32P rin(rectIn.getLx() + abs(p.x), rectIn.getLy() + abs(p.y)); |
| TRaster32P rout(r->getSize()); |
| |
| tileRaster(rTex, rin); |
| TRop::resample(rout, rin, affine.place(rin->getCenterD(), rout->getCenterD() - convert(p))); |
| rTex = rout; |
| p = TPoint(); |
| } else { |
| if (m_params.m_type == TTextureParams::AUTOMATIC) |
| p += rTex->getCenter() - computeCentroid(r); |
| p.x = (p.x % m_texture->getLx()); |
| p.y = (p.y % m_texture->getLy()); |
| } |
| |
| applyTexture(rTex, r, p); |
| |
| return true; |
| } |
| |
| |
| |
| namespace |
| { |
| |
| TRaster32P makeSimpleRaster() |
| { |
| TRaster32P ras(2, 2); |
| ras->fill(TPixel32::White); |
| return ras; |
| } |
| |
| TColorStyle::Declaration s2(new TTextureStyle(makeSimpleRaster(), TFilePath())); |
| } |
| |