2019-11-23 20:27:39 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
|
|
|
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
|
|
|
|
2022-10-01 16:24:52 +08:00
|
|
|
https://axmolengine.github.io/
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
|
|
|
#include "base/CCNinePatchImageParser.h"
|
|
|
|
#include "platform/CCImage.h"
|
|
|
|
#include "base/CCDirector.h"
|
|
|
|
|
2022-07-11 17:50:21 +08:00
|
|
|
NS_AX_BEGIN
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
NinePatchImageParser::~NinePatchImageParser() {}
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
NinePatchImageParser::NinePatchImageParser() : _image(nullptr), _imageFrame(Rect::ZERO), _isRotated(false) {}
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
NinePatchImageParser::NinePatchImageParser(Image* image) : _image(image), _imageFrame(Rect::ZERO), _isRotated(false)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
this->_imageFrame = Rect(0, 0, image->getWidth(), image->getHeight());
|
2022-07-16 10:43:05 +08:00
|
|
|
AXASSERT(image->getPixelFormat() == backend::PixelFormat::RGBA8,
|
2019-11-23 20:27:39 +08:00
|
|
|
"unsupported format, currently only supports rgba8888");
|
|
|
|
}
|
|
|
|
|
|
|
|
NinePatchImageParser::NinePatchImageParser(Image* image, const Rect& frame, bool rotated)
|
2021-12-25 10:04:45 +08:00
|
|
|
: _image(image), _imageFrame(frame), _isRotated(rotated)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
AXASSERT(image->getPixelFormat() == backend::PixelFormat::RGBA8,
|
2019-11-23 20:27:39 +08:00
|
|
|
"unsupported format, currently only supports rgba8888");
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
int NinePatchImageParser::getFrameHeight() const
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
if (_isRotated)
|
|
|
|
{
|
|
|
|
return _imageFrame.size.width;
|
|
|
|
}
|
|
|
|
return _imageFrame.size.height;
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
int NinePatchImageParser::getFrameWidth() const
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
if (_isRotated)
|
|
|
|
{
|
|
|
|
return _imageFrame.size.height;
|
|
|
|
}
|
|
|
|
return _imageFrame.size.width;
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
int NinePatchImageParser::getPixelOriginOffset(Direction direction) const
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
int imageWidth = _image->getWidth();
|
|
|
|
int frameWidth = this->getFrameWidth();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
int topLineLeftOffset = (int)_imageFrame.origin.y * imageWidth * 4 + (int)_imageFrame.origin.x * 4;
|
2021-12-25 10:04:45 +08:00
|
|
|
if (direction == Direction::HORIZONTAL)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
return topLineLeftOffset;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
if (_isRotated)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
return topLineLeftOffset + (frameWidth - 1) * 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return topLineLeftOffset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
Vec2 NinePatchImageParser::parseHorizontalMargin() const
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
unsigned char* data = _image->getData();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
|
|
|
data = data + this->getPixelOriginOffset(Direction::HORIZONTAL);
|
2019-11-23 20:27:39 +08:00
|
|
|
unsigned char lastPixel = *(data + 3);
|
2021-12-25 10:04:45 +08:00
|
|
|
int x1 = 0;
|
|
|
|
int x2 = 0;
|
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
int length = _imageFrame.origin.x + this->getFrameWidth();
|
2021-12-25 10:04:45 +08:00
|
|
|
for (int i = (int)_imageFrame.origin.x; i <= length; i++)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
unsigned char pixel = *(data + (i - (int)_imageFrame.origin.x) * 4 + 3);
|
|
|
|
if (pixel != lastPixel)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
if (pixel > 0)
|
|
|
|
{
|
|
|
|
x1 = (i - (int)_imageFrame.origin.x);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x2 = (i - (int)_imageFrame.origin.x);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lastPixel = pixel;
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
return Vec2(x1, x2);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
Vec2 NinePatchImageParser::parseVerticalMargin() const
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
unsigned char* data = _image->getData();
|
2021-12-25 10:04:45 +08:00
|
|
|
int imageWidth = _image->getWidth();
|
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
int y1 = 0;
|
|
|
|
int y2 = 0;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
|
|
|
data = data + this->getPixelOriginOffset(Direction::VERTICAL);
|
2019-11-23 20:27:39 +08:00
|
|
|
unsigned char lastPixel = *(data + 3);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
int length = (int)(_imageFrame.origin.y + this->getFrameHeight());
|
2021-12-25 10:04:45 +08:00
|
|
|
for (int i = _imageFrame.origin.y; i <= length; i++)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
unsigned char pixel = *(data + (i - (int)_imageFrame.origin.y) * imageWidth * 4 + 3);
|
2021-12-25 10:04:45 +08:00
|
|
|
if (pixel != lastPixel)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
if (pixel > 0)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
y1 = (i - (int)_imageFrame.origin.y);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
y2 = (i - (int)_imageFrame.origin.y);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lastPixel = pixel;
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
return Vec2(y1, y2);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Rect NinePatchImageParser::parseCapInset() const
|
|
|
|
{
|
|
|
|
Rect capInsets;
|
|
|
|
Vec2 horizontalLine = this->parseHorizontalMargin();
|
2021-12-25 10:04:45 +08:00
|
|
|
Vec2 verticalLine = this->parseVerticalMargin();
|
|
|
|
|
|
|
|
if (_isRotated)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
capInsets = Rect(verticalLine.y, _imageFrame.size.height - horizontalLine.y, verticalLine.y - verticalLine.x,
|
|
|
|
horizontalLine.y - horizontalLine.x);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
capInsets = Rect(horizontalLine.x, verticalLine.x, horizontalLine.y - horizontalLine.x,
|
2019-11-23 20:27:39 +08:00
|
|
|
verticalLine.y - verticalLine.x);
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2022-07-16 10:43:05 +08:00
|
|
|
capInsets = AX_RECT_PIXELS_TO_POINTS(capInsets);
|
2019-11-23 20:27:39 +08:00
|
|
|
return capInsets;
|
|
|
|
}
|
|
|
|
|
2022-08-08 18:02:17 +08:00
|
|
|
void NinePatchImageParser::setSpriteFrameInfo(Image* image, const ax::Rect& frameRect, bool rotated)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
this->_image = image;
|
2022-07-16 10:43:05 +08:00
|
|
|
AXASSERT(image->getPixelFormat() == backend::PixelFormat::RGBA8,
|
2019-11-23 20:27:39 +08:00
|
|
|
"unsupported format, currently only supports rgba8888");
|
|
|
|
this->_imageFrame = frameRect;
|
2021-12-25 10:04:45 +08:00
|
|
|
this->_isRotated = rotated;
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
bool NinePatchImageParser::isNinePatchImage(std::string_view filepath)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
size_t length = filepath.length();
|
2021-12-25 10:04:45 +08:00
|
|
|
if (length < 7)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
if (filepath.compare(length - 6, 6, ".9.png") == 0)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-11 17:50:21 +08:00
|
|
|
NS_AX_END
|