Merge tag '2.5.2'

Conflicts:
	lime/graphics/utils/ImageDataUtil.hx
This commit is contained in:
James Gray
2015-08-06 18:04:28 -05:00
85 changed files with 3175 additions and 1120 deletions

View File

@@ -29,6 +29,7 @@
<set name="NATIVE_TOOLKIT_PATH" value="lib" unless="NATIVE_TOOLKIT_PATH" />
<set name="NATIVE_TOOLKIT_CURL_SSL" value="1" />
<set name="NATIVE_TOOLKIT_CURL_DISABLE_AXTLS_NONBLOCKING" value="1" />
<set name="NATIVE_TOOLKIT_SDL_STATIC" value="1" />
<set name="NATIVE_TOOLKIT_SDL_ANGLE" value="1" if="LIME_SDL_ANGLE" />

View File

@@ -23,7 +23,6 @@ namespace lime {
int height;
int offsetX;
int offsetY;
bool transparent;
int width;
private:

View File

@@ -28,8 +28,9 @@ namespace lime {
Bytes *data;
PixelFormat format;
int height;
int width;
bool premultiplied;
bool transparent;
int width;
private:

View File

@@ -7,9 +7,9 @@ namespace lime {
enum PixelFormat {
RGBA,
ARGB,
BGRA
RGBA32,
ARGB32,
BGRA32
};

View File

@@ -16,6 +16,7 @@ namespace lime {
virtual void Flip () = 0;
virtual value Lock () = 0;
virtual const char* Type () = 0;
virtual void Unlock () = 0;
Window* currentWindow;

View File

@@ -10,6 +10,7 @@
#include <math/Vector2.h>
#include <system/System.h>
#include <utils/Bytes.h>
#include <stdint.h>
namespace lime {
@@ -22,9 +23,9 @@ namespace lime {
static void ColorTransform (Image* image, Rectangle* rect, ColorMatrix* ColorMatrix);
static void CopyChannel (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int srcChannel, int destChannel);
static void CopyPixels (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, bool mergeAlpha);
static void FillRect (Image* image, Rectangle* rect, int color);
static void FloodFill (Image* image, int x, int y, int color);
static void CopyPixels (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, Image* alphaImage, Vector2* alphaPoint, bool mergeAlpha);
static void FillRect (Image* image, Rectangle* rect, int32_t color);
static void FloodFill (Image* image, int x, int y, int32_t color);
static void GetPixels (Image* image, Rectangle* rect, PixelFormat format, Bytes* pixels);
static void Merge (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int redMultiplier, int greenMultiplier, int blueMultiplier, int alphaMultiplier);
static void MultiplyAlpha (Image* image);
@@ -37,6 +38,32 @@ namespace lime {
};
class ImageDataView {
public:
ImageDataView (Image* image, Rectangle* rect);
void Clip (int x, int y, int width, int height);
int Row (int y);
int x;
int y;
int width;
int height;
private:
Image* image;
int offset;
Rectangle* rect;
int stride;
};
}

View File

@@ -4,6 +4,7 @@
#include <hx/CFFI.h>
#include <system/System.h>
#include <stdint.h>
namespace lime {
@@ -20,16 +21,24 @@ namespace lime {
float GetAlphaMultiplier ();
float GetAlphaOffset ();
void GetAlphaTable (unsigned char* table);
float GetBlueMultiplier ();
float GetBlueOffset ();
int GetColor ();
void GetBlueTable (unsigned char* table);
int32_t GetColor ();
float GetGreenMultiplier ();
float GetGreenOffset ();
void GetGreenTable (unsigned char* table);
float GetRedMultiplier ();
float GetRedOffset ();
void GetRedTable (unsigned char* table);
float data[20];
private:
void GetDataTable (unsigned char* table, float multiplier, float offset);
};

View File

@@ -17,6 +17,8 @@ namespace lime {
Rectangle (double x, double y, double width, double height);
Rectangle (value rect);
void Contract (double x, double y, double width, double height);
double height;
double width;
double x;

View File

@@ -0,0 +1,211 @@
#ifndef LIME_MATH_COLOR_RGBA_H
#define LIME_MATH_COLOR_RGBA_H
#include <graphics/PixelFormat.h>
#include <stdint.h>
#include <math.h>
namespace lime {
int __alpha16[0xFF + 1];
int __clamp[0xFF + 0xFF + 1];
static int a16;
static double unmult;
int initValues () {
for (int i = 0; i < 256; i++) {
__alpha16[i] = ceil ((float)(i + 1) * ((1 << 16) / 0xFF));
}
for (int i = 0; i < 0xFF; i++) {
__clamp[i] = i;
}
for (int i = 0xFF; i < (0xFF + 0xFF + 1); i++) {
__clamp[i] = 0xFF;
}
return 0;
}
static int initValues_ = initValues ();
struct RGBA {
public:
inline RGBA () {
r = 0;
g = 0;
b = 0;
a = 0;
}
inline RGBA (int32_t rgba) {
r = (rgba >> 24) & 0xFF;
g = (rgba >> 16) & 0xFF;
b = (rgba >> 8) & 0xFF;
a = rgba & 0xFF;
}
inline RGBA (unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
Set (r, g, b, a);
}
inline int32_t Get () {
int32_t value = ((r & 0xFF) << 24) | ((g & 0xFF) << 16) | ((b & 0xFF) << 8) | (a & 0xFF);
return value;
}
inline void MultiplyAlpha () {
if (a == 0) {
Set (0, 0, 0, 0);
} else if (a != 0xFF) {
a16 = __alpha16[a];
Set ((r * a16) >> 16, (g * a16) >> 16, (b * a16) >> 16, a);
}
}
inline void UnmultiplyAlpha () {
if (a != 0 && a != 0xFF) {
unmult = 255.0 / a;
Set (__clamp[(int)(r * unmult)], __clamp[(int)(g * unmult)], __clamp[(int)(b * unmult)], a);
}
}
inline void ReadUInt8 (const unsigned char* data, int offset, PixelFormat format, bool premultiplied) {
switch (format) {
case BGRA32:
Set (data[offset + 2], data[offset + 1], data[offset], data[offset + 3]);
break;
case RGBA32:
Set (data[offset], data[offset + 1], data[offset + 2], data[offset + 3]);
break;
case ARGB32:
Set (data[offset + 1], data[offset + 2], data[offset + 3], data[offset]);
break;
}
if (premultiplied) {
UnmultiplyAlpha ();
}
}
inline void Set (unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
this->r = r;
this->g = g;
this->b = b;
this->a = a;
}
inline void WriteUInt8 (unsigned char* data, int offset, PixelFormat format, bool premultiplied) {
if (premultiplied) {
MultiplyAlpha ();
}
switch (format) {
case BGRA32:
data[offset] = b;
data[offset + 1] = g;
data[offset + 2] = r;
data[offset + 3] = a;
break;
case RGBA32:
data[offset] = r;
data[offset + 1] = g;
data[offset + 2] = b;
data[offset + 3] = a;
break;
case ARGB32:
data[offset] = a;
data[offset + 1] = r;
data[offset + 2] = g;
data[offset + 3] = b;
break;
}
}
inline bool operator == (RGBA& rgba) {
return (a == rgba.a && r == rgba.r && g == rgba.g && b == rgba.b);
}
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
};
}
#endif

View File

@@ -127,6 +127,23 @@ namespace lime {
}
value lime_bytes_from_data_pointer (value data, value length) {
int size = val_int (length);
intptr_t ptr = (intptr_t)val_float (data);
Bytes bytes = Bytes (size);
if (ptr) {
memcpy (bytes.Data (), (const void*)ptr, size);
}
return bytes.Value ();
}
value lime_bytes_get_data_pointer (value bytes) {
Bytes data = Bytes (bytes);
@@ -135,6 +152,14 @@ namespace lime {
}
value lime_bytes_read_file (value path) {
Bytes data = Bytes (val_os_string (path));
return data.Value ();
}
void lime_font_destroy (value handle) {
#ifdef LIME_FREETYPE
@@ -508,32 +533,49 @@ namespace lime {
}
value lime_image_data_util_copy_pixels (value image, value sourceImage, value sourceRect, value destPoint, value mergeAlpha) {
value lime_image_data_util_copy_pixels (value *arg, int nargs) {
enum { image, sourceImage, sourceRect, destPoint, alphaImage, alphaPoint, mergeAlpha };
Image _image = Image (arg[image]);
Image _sourceImage = Image (arg[sourceImage]);
Rectangle _sourceRect = Rectangle (arg[sourceRect]);
Vector2 _destPoint = Vector2 (arg[destPoint]);
if (val_is_null (arg[alphaImage])) {
ImageDataUtil::CopyPixels (&_image, &_sourceImage, &_sourceRect, &_destPoint, 0, 0, val_bool (arg[mergeAlpha]));
} else {
Image _alphaImage = Image (arg[alphaImage]);
Vector2 _alphaPoint = Vector2 (arg[alphaPoint]);
ImageDataUtil::CopyPixels (&_image, &_sourceImage, &_sourceRect, &_destPoint, &_alphaImage, &_alphaPoint, val_bool (arg[mergeAlpha]));
}
Image _image = Image (image);
Image _sourceImage = Image (sourceImage);
Rectangle _sourceRect = Rectangle (sourceRect);
Vector2 _destPoint = Vector2 (destPoint);
ImageDataUtil::CopyPixels (&_image, &_sourceImage, &_sourceRect, &_destPoint, val_bool (mergeAlpha));
return alloc_null ();
}
value lime_image_data_util_fill_rect (value image, value rect, value color) {
value lime_image_data_util_fill_rect (value image, value rect, value rg, value ba) {
Image _image = Image (image);
Rectangle _rect = Rectangle (rect);
ImageDataUtil::FillRect (&_image, &_rect, val_number (color));
int32_t color = (val_int (rg) << 16) | val_int (ba);
ImageDataUtil::FillRect (&_image, &_rect, color);
return alloc_null ();
}
value lime_image_data_util_flood_fill (value image, value x, value y, value color) {
value lime_image_data_util_flood_fill (value image, value x, value y, value rg, value ba) {
Image _image = Image (image);
ImageDataUtil::FloodFill (&_image, val_number (x), val_number (y), val_number (color));
int32_t color = (val_int (rg) << 16) | val_int (ba);
ImageDataUtil::FloodFill (&_image, val_number (x), val_number (y), color);
return alloc_null ();
}
@@ -843,6 +885,14 @@ namespace lime {
}
value lime_renderer_get_type (value renderer) {
Renderer* targetRenderer = (Renderer*)(intptr_t)val_float (renderer);
return alloc_string (targetRenderer->Type ());
}
value lime_renderer_lock (value renderer) {
return ((Renderer*)(intptr_t)val_float (renderer))->Lock ();
@@ -1120,7 +1170,9 @@ namespace lime {
DEFINE_PRIM (lime_application_set_frame_rate, 2);
DEFINE_PRIM (lime_application_update, 1);
DEFINE_PRIM (lime_audio_load, 1);
DEFINE_PRIM (lime_bytes_from_data_pointer, 2);
DEFINE_PRIM (lime_bytes_get_data_pointer, 1);
DEFINE_PRIM (lime_bytes_read_file, 1);
DEFINE_PRIM (lime_font_get_ascender, 1);
DEFINE_PRIM (lime_font_get_descender, 1);
DEFINE_PRIM (lime_font_get_family_name, 1);
@@ -1143,9 +1195,9 @@ namespace lime {
DEFINE_PRIM (lime_gamepad_get_device_name, 1);
DEFINE_PRIM (lime_image_data_util_color_transform, 3);
DEFINE_PRIM_MULT (lime_image_data_util_copy_channel);
DEFINE_PRIM (lime_image_data_util_copy_pixels, 5);
DEFINE_PRIM (lime_image_data_util_fill_rect, 3);
DEFINE_PRIM (lime_image_data_util_flood_fill, 4);
DEFINE_PRIM_MULT (lime_image_data_util_copy_pixels);
DEFINE_PRIM (lime_image_data_util_fill_rect, 4);
DEFINE_PRIM (lime_image_data_util_flood_fill, 5);
DEFINE_PRIM (lime_image_data_util_get_pixels, 4);
DEFINE_PRIM_MULT (lime_image_data_util_merge);
DEFINE_PRIM (lime_image_data_util_multiply_alpha, 1);
@@ -1172,6 +1224,7 @@ namespace lime {
DEFINE_PRIM (lime_png_decode_file, 2);
DEFINE_PRIM (lime_renderer_create, 1);
DEFINE_PRIM (lime_renderer_flip, 1);
DEFINE_PRIM (lime_renderer_get_type, 1);
DEFINE_PRIM (lime_renderer_lock, 1);
DEFINE_PRIM (lime_renderer_unlock, 1);
DEFINE_PRIM (lime_render_event_manager_register, 2);

View File

@@ -15,7 +15,8 @@ namespace lime {
AutoGCRoot* Application::callback = 0;
SDLApplication* SDLApplication::currentApplication = 0;
std::map<int, std::map<int, int> > gamepadsAxisMap;
const int analogAxisDeadZone = 1000;
SDLApplication::SDLApplication () {
@@ -239,9 +240,36 @@ namespace lime {
case SDL_CONTROLLERAXISMOTION:
if (gamepadsAxisMap[event->caxis.which].empty()) {
gamepadsAxisMap[event->caxis.which][event->caxis.axis] = event->caxis.value;
}
else if (gamepadsAxisMap[event->caxis.which][event->caxis.axis] == event->caxis.value) {
break;
}
gamepadEvent.type = AXIS_MOVE;
gamepadEvent.axis = event->caxis.axis;
gamepadEvent.id = event->caxis.which;
if (event->caxis.value > -analogAxisDeadZone && event->caxis.value < analogAxisDeadZone) {
if (gamepadsAxisMap[event->caxis.which][event->caxis.axis] != 0) {
gamepadsAxisMap[event->caxis.which][event->caxis.axis] = 0;
gamepadEvent.axisValue = 0;
GamepadEvent::Dispatch (&gamepadEvent);
}
break;
}
gamepadsAxisMap[event->caxis.which][event->caxis.axis] = event->caxis.value;
gamepadEvent.axisValue = event->caxis.value / 32768.0;
GamepadEvent::Dispatch (&gamepadEvent);

View File

@@ -31,6 +31,15 @@ namespace lime {
sdlRenderer = SDL_CreateRenderer (sdlWindow, -1, sdlFlags);
if (!sdlRenderer && (sdlFlags & SDL_RENDERER_ACCELERATED)) {
sdlFlags &= ~SDL_RENDERER_ACCELERATED;
sdlFlags |= SDL_RENDERER_SOFTWARE;
sdlRenderer = SDL_CreateRenderer (sdlWindow, -1, sdlFlags);
}
if (!sdlRenderer) {
printf ("Could not create SDL renderer: %s.\n", SDL_GetError ());
@@ -95,6 +104,30 @@ namespace lime {
}
const char* SDLRenderer::Type () {
if (sdlRenderer) {
SDL_RendererInfo info;
SDL_GetRendererInfo (sdlRenderer, &info);
if (info.flags & SDL_RENDERER_SOFTWARE) {
return "software";
} else {
return "opengl";
}
}
return "none";
}
void SDLRenderer::Unlock () {
if (sdlTexture) {

View File

@@ -18,6 +18,7 @@ namespace lime {
virtual void Flip ();
virtual value Lock ();
virtual const char* Type ();
virtual void Unlock ();
SDL_Renderer* sdlRenderer;

View File

@@ -8,7 +8,6 @@ namespace lime {
static int id_height;
static int id_offsetX;
static int id_offsetY;
static int id_transparent;
static int id_width;
static bool init = false;
@@ -19,7 +18,6 @@ namespace lime {
height = 0;
offsetX = 0;
offsetY = 0;
transparent = true;
width = 0;
}
@@ -33,7 +31,6 @@ namespace lime {
id_height = val_id ("height");
id_offsetX = val_id ("offsetX");
id_offsetY = val_id ("offsetY");
id_transparent = val_id ("transparent");
id_width = val_id ("width");
init = true;
@@ -44,7 +41,6 @@ namespace lime {
buffer = new ImageBuffer (val_field (image, id_buffer));
offsetX = val_int (val_field (image, id_offsetX));
offsetY = val_int (val_field (image, id_offsetY));
transparent = val_bool (val_field (image, id_transparent));
}

View File

@@ -9,8 +9,9 @@ namespace lime {
static int id_data;
static int id_format;
static int id_height;
static int id_width;
static int id_premultiplied;
static int id_transparent;
static int id_width;
static bool init = false;
@@ -19,8 +20,9 @@ namespace lime {
width = 0;
height = 0;
bitsPerPixel = 32;
format = RGBA;
format = RGBA32;
data = 0;
premultiplied = false;
transparent = false;
}
@@ -37,6 +39,7 @@ namespace lime {
id_height = val_id ("height");
id_data = val_id ("data");
id_format = val_id ("format");
id_premultiplied = val_id ("premultiplied");
init = true;
}
@@ -48,6 +51,7 @@ namespace lime {
transparent = val_bool (val_field (imageBuffer, id_transparent));
value data_value = val_field (imageBuffer, id_data);
value buffer_value = val_field (data_value, id_buffer);
premultiplied = val_bool (val_field (imageBuffer, id_premultiplied));
data = new Bytes (buffer_value);
}
@@ -119,6 +123,7 @@ namespace lime {
id_height = val_id ("height");
id_data = val_id ("data");
id_format = val_id ("format");
id_premultiplied = val_id ("premultiplied");
init = true;
}
@@ -130,6 +135,7 @@ namespace lime {
alloc_field (mValue, id_data, data ? data->Value () : alloc_null ());
alloc_field (mValue, id_transparent, alloc_bool (transparent));
alloc_field (mValue, id_format, alloc_int (format));
alloc_field (mValue, id_premultiplied, alloc_bool (premultiplied));
return mValue;
}

View File

@@ -368,16 +368,37 @@ namespace lime {
}
value lime_cairo_image_surface_get_data (value handle) {
return alloc_float ((intptr_t)cairo_image_surface_get_data ((cairo_surface_t*)(intptr_t)val_float (handle)));
}
value lime_cairo_image_surface_get_format (value handle) {
return alloc_int ((int)cairo_image_surface_get_format ((cairo_surface_t*)(intptr_t)val_float (handle)));
}
value lime_cairo_image_surface_get_height (value handle) {
return alloc_int ((intptr_t)cairo_image_surface_get_height ((cairo_surface_t*)(intptr_t)val_float (handle)));
return alloc_int (cairo_image_surface_get_height ((cairo_surface_t*)(intptr_t)val_float (handle)));
}
value lime_cairo_image_surface_get_stride (value handle) {
return alloc_int (cairo_image_surface_get_stride ((cairo_surface_t*)(intptr_t)val_float (handle)));
}
value lime_cairo_image_surface_get_width (value handle) {
return alloc_int ((intptr_t)cairo_image_surface_get_width ((cairo_surface_t*)(intptr_t)val_float (handle)));
return alloc_int (cairo_image_surface_get_width ((cairo_surface_t*)(intptr_t)val_float (handle)));
}
@@ -993,7 +1014,10 @@ namespace lime {
DEFINE_PRIM (lime_cairo_identity_matrix, 1);
DEFINE_PRIM (lime_cairo_image_surface_create, 3);
DEFINE_PRIM (lime_cairo_image_surface_create_for_data, 5);
DEFINE_PRIM (lime_cairo_image_surface_get_data, 1);
DEFINE_PRIM (lime_cairo_image_surface_get_format, 1);
DEFINE_PRIM (lime_cairo_image_surface_get_height, 1);
DEFINE_PRIM (lime_cairo_image_surface_get_stride, 1);
DEFINE_PRIM (lime_cairo_image_surface_get_width, 1);
DEFINE_PRIM (lime_cairo_in_clip, 3);
DEFINE_PRIM (lime_cairo_in_fill, 3);

View File

@@ -1,82 +1,45 @@
#include <graphics/utils/ImageDataUtil.h>
#include <math/color/RGBA.h>
#include <system/System.h>
#include <utils/QuickVec.h>
#include <math.h>
namespace lime {
static int __alpha16[0xFF + 1];
static int __clamp[0xFF + 0xFF + 1];
int initValues () {
for (int i = 0; i < 256; i++) {
// Seem to need +1 to get the same results as Haxe in multiplyAlpha
__alpha16[i] = (i + 1) * ((1 << 16) / 0xFF);
}
for (int i = 0; i < 0xFF; i++) {
__clamp[i] = i;
}
for (int i = 0xFF; i < (0xFF + 0xFF + 1); i++) {
__clamp[i] = 0xFF;
}
return 0;
}
static int initValues_ = initValues ();
void ImageDataUtil::ColorTransform (Image* image, Rectangle* rect, ColorMatrix* colorMatrix) {
int stride = image->buffer->Stride ();
int offset;
int rowStart = int (rect->y + image->offsetY);
int rowEnd = int (rect->y + rect->height + image->offsetY);
int columnStart = int (rect->x + image->offsetX);
int columnEnd = int (rect->x + rect->width + image->offsetX);
PixelFormat format = image->buffer->format;
bool premultiplied = image->buffer->premultiplied;
uint8_t* data = (uint8_t*)image->buffer->data->Data ();
int r, g, b, a, ex = 0;
float alphaMultiplier = colorMatrix->GetAlphaMultiplier ();
float redMultiplier = colorMatrix->GetRedMultiplier ();
float greenMultiplier = colorMatrix->GetGreenMultiplier ();
float blueMultiplier = colorMatrix->GetBlueMultiplier ();
int alphaOffset = colorMatrix->GetAlphaOffset ();
int redOffset = colorMatrix->GetRedOffset ();
int greenOffset = colorMatrix->GetGreenOffset ();
int blueOffset = colorMatrix->GetBlueOffset ();
ImageDataView dataView = ImageDataView (image, rect);
for (int row = rowStart; row < rowEnd; row++) {
unsigned char alphaTable[256];
unsigned char redTable[256];
unsigned char greenTable[256];
unsigned char blueTable[256];
colorMatrix->GetAlphaTable (alphaTable);
colorMatrix->GetRedTable (redTable);
colorMatrix->GetGreenTable (greenTable);
colorMatrix->GetBlueTable (blueTable);
int row, offset;
RGBA pixel;
for (int y = 0; y < dataView.height; y++) {
for (int column = columnStart; column < columnEnd; column++) {
row = dataView.Row (y);
for (int x = 0; x < dataView.width; x++) {
offset = (row * stride) + (column * 4);
offset = row + (x * 4);
a = (data[offset + 3] * alphaMultiplier) + alphaOffset;
ex = a > 0xFF ? a - 0xFF : 0;
b = (data[offset + 2] * blueMultiplier) + blueOffset + ex;
ex = b > 0xFF ? b - 0xFF : 0;
g = (data[offset + 1] * greenMultiplier) + greenOffset + ex;
ex = g > 0xFF ? g - 0xFF : 0;
r = (data[offset] * redMultiplier) + redOffset + ex;
data[offset] = r > 0xFF ? 0xFF : r;
data[offset + 1] = g > 0xFF ? 0xFF : g;
data[offset + 2] = b > 0xFF ? 0xFF : b;
data[offset + 3] = a > 0xFF ? 0xFF : a;
pixel.ReadUInt8 (data, offset, format, premultiplied);
pixel.Set (redTable[pixel.r], greenTable[pixel.g], blueTable[pixel.b], alphaTable[pixel.a]);
pixel.WriteUInt8 (data, offset, format, premultiplied);
}
@@ -87,36 +50,54 @@ namespace lime {
void ImageDataUtil::CopyChannel (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int srcChannel, int destChannel) {
int srcStride = sourceImage->buffer->Stride ();
int srcPosition = ((sourceRect->x + sourceImage->offsetX) * 4) + (srcStride * (sourceRect->y + sourceImage->offsetY)) + srcChannel;
int srcRowOffset = srcStride - int (4 * (sourceRect->width + sourceImage->offsetX));
int srcRowEnd = 4 * (sourceRect->x + sourceImage->offsetX + sourceRect->width);
uint8_t* srcData = (uint8_t*)sourceImage->buffer->data->Data ();
int destStride = image->buffer->Stride ();
int destPosition = ((destPoint->x + image->offsetX) * 4) + (destStride * (destPoint->y + image->offsetY)) + destChannel;
int destRowOffset = destStride - int (4 * (sourceRect->width + image->offsetX));
int destRowEnd = 4 * (destPoint->x + image->offsetX + sourceRect->width);
uint8_t* destData = (uint8_t*)image->buffer->data->Data ();
int length = sourceRect->width * sourceRect->height;
ImageDataView srcView = ImageDataView (sourceImage, sourceRect);
Rectangle destRect = Rectangle (destPoint->x, destPoint->y, srcView.width, srcView.height);
ImageDataView destView = ImageDataView (image, &destRect);
for (int i = 0; i < length; i++) {
PixelFormat srcFormat = sourceImage->buffer->format;
PixelFormat destFormat = image->buffer->format;
bool srcPremultiplied = sourceImage->buffer->premultiplied;
bool destPremultiplied = image->buffer->premultiplied;
int srcPosition, destPosition;
RGBA srcPixel, destPixel;
unsigned char value = 0;
for (int y = 0; y < destView.height; y++) {
destData[destPosition] = srcData[srcPosition];
srcPosition = srcView.Row (y);
destPosition = destView.Row (y);
srcPosition += 4;
destPosition += 4;
if ((srcPosition % srcStride) > srcRowEnd) {
for (int x = 0; x < destView.width; x++) {
srcPosition += srcRowOffset;
srcPixel.ReadUInt8 (srcData, srcPosition, srcFormat, srcPremultiplied);
destPixel.ReadUInt8 (destData, destPosition, destFormat, destPremultiplied);
}
if ((destPosition % destStride) > destRowEnd) {
switch (srcChannel) {
case 0: value = srcPixel.r; break;
case 1: value = srcPixel.g; break;
case 2: value = srcPixel.b; break;
case 3: value = srcPixel.a; break;
}
destPosition += destRowOffset;
switch (destChannel) {
case 0: destPixel.r = value; break;
case 1: destPixel.g = value; break;
case 2: destPixel.b = value; break;
case 3: destPixel.a = value; break;
}
destPixel.WriteUInt8 (destData, destPosition, destFormat, destPremultiplied);
srcPosition += 4;
destPosition += 4;
}
@@ -125,35 +106,37 @@ namespace lime {
}
void ImageDataUtil::CopyPixels (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, bool mergeAlpha) {
int rowOffset = int (destPoint->y + image->offsetY - sourceRect->y - sourceImage->offsetY);
int columnOffset = int (destPoint->x + image->offsetX - sourceRect->x - sourceImage->offsetY);
void ImageDataUtil::CopyPixels (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, Image* alphaImage, Vector2* alphaPoint, bool mergeAlpha) {
uint8_t* sourceData = (uint8_t*)sourceImage->buffer->data->Data ();
int sourceStride = sourceImage->buffer->Stride ();
int sourceOffset = 0;
uint8_t* destData = (uint8_t*)image->buffer->data->Data ();
uint8_t* data = (uint8_t*)image->buffer->data->Data ();
int stride = image->buffer->Stride ();
int offset = 0;
ImageDataView sourceView = ImageDataView (sourceImage, sourceRect);
Rectangle destRect = Rectangle (destPoint->x, destPoint->y, sourceView.width, sourceView.height);
ImageDataView destView = ImageDataView (image, &destRect);
int rows = sourceRect->y + sourceRect->height + sourceImage->offsetY;
int columns = sourceRect->x + sourceRect->width + sourceImage->offsetX;
PixelFormat sourceFormat = sourceImage->buffer->format;
PixelFormat destFormat = image->buffer->format;
bool sourcePremultiplied = sourceImage->buffer->premultiplied;
bool destPremultiplied = image->buffer->premultiplied;
int sourcePosition, destPosition;
RGBA sourcePixel;
if (!mergeAlpha || !sourceImage->buffer->transparent) {
for (int row = sourceRect->y + sourceImage->offsetY; row < rows; row++) {
for (int y = 0; y < destView.height; y++) {
for (int column = sourceRect->x + sourceImage->offsetX; column < columns; column++) {
sourcePosition = sourceView.Row (y);
destPosition = destView.Row (y);
for (int x = 0; x < destView.width; x++) {
sourceOffset = (row * sourceStride) + (column * 4);
offset = ((row + rowOffset) * stride) + ((column + columnOffset) * 4);
sourcePixel.ReadUInt8 (sourceData, sourcePosition, sourceFormat, sourcePremultiplied);
sourcePixel.WriteUInt8 (destData, destPosition, destFormat, destPremultiplied);
data[offset] = sourceData[sourceOffset];
data[offset + 1] = sourceData[sourceOffset + 1];
data[offset + 2] = sourceData[sourceOffset + 2];
data[offset + 3] = sourceData[sourceOffset + 3];
sourcePosition += 4;
destPosition += 4;
}
@@ -161,75 +144,95 @@ namespace lime {
} else {
float sourceAlpha;
float destAlpha;
float outA;
float oneMinusSourceAlpha;
float sourceAlpha, destAlpha, oneMinusSourceAlpha, blendAlpha;
RGBA destPixel;
for (int row = sourceRect->y + sourceImage->offsetY; row < rows; row++) {
if (alphaImage == 0) {
for (int column = sourceRect->x + sourceImage->offsetX; column < columns; column++) {
for (int y = 0; y < destView.height; y++) {
sourceOffset = (row * sourceStride) + (column * 4);
offset = ((row + rowOffset) * stride) + ((column + columnOffset) * 4);
sourcePosition = sourceView.Row (y);
destPosition = destView.Row (y);
sourceAlpha = sourceData[sourceOffset + 3] / 255.0;
destAlpha = data[offset + 3] / 255.0;
oneMinusSourceAlpha = (1 - sourceAlpha);
outA = sourceAlpha + destAlpha * oneMinusSourceAlpha;
data[offset + 0] = __clamp[int (0.5 + ((sourceData[sourceOffset + 0] * sourceAlpha + data[offset + 0] * destAlpha * oneMinusSourceAlpha) / outA))];
data[offset + 1] = __clamp[int (0.5 + ((sourceData[sourceOffset + 1] * sourceAlpha + data[offset + 1] * destAlpha * oneMinusSourceAlpha) / outA))];
data[offset + 2] = __clamp[int (0.5 + ((sourceData[sourceOffset + 2] * sourceAlpha + data[offset + 2] * destAlpha * oneMinusSourceAlpha) / outA))];
data[offset + 3] = __clamp[int (0.5 + (outA * 255.0))];
for (int x = 0; x < destView.width; x++) {
sourcePixel.ReadUInt8 (sourceData, sourcePosition, sourceFormat, sourcePremultiplied);
destPixel.ReadUInt8 (destData, destPosition, destFormat, destPremultiplied);
sourceAlpha = sourcePixel.a / 255.0;
destAlpha = destPixel.a / 255.0;
oneMinusSourceAlpha = 1 - sourceAlpha;
blendAlpha = sourceAlpha + (destAlpha * oneMinusSourceAlpha);
if (blendAlpha == 0) {
destPixel.Set (0, 0, 0, 0);
} else {
destPixel.r = __clamp[int (0.5 + (sourcePixel.r * sourceAlpha + destPixel.r * destAlpha * oneMinusSourceAlpha) / blendAlpha)];
destPixel.g = __clamp[int (0.5 + (sourcePixel.g * sourceAlpha + destPixel.g * destAlpha * oneMinusSourceAlpha) / blendAlpha)];
destPixel.b = __clamp[int (0.5 + (sourcePixel.b * sourceAlpha + destPixel.b * destAlpha * oneMinusSourceAlpha) / blendAlpha)];
destPixel.a = __clamp[int (0.5 + blendAlpha * 255.0)];
}
destPixel.WriteUInt8 (destData, destPosition, destFormat, destPremultiplied);
sourcePosition += 4;
destPosition += 4;
}
}
}
}
}
void ImageDataUtil::FillRect (Image* image, Rectangle* rect, int color) {
int* data = (int*)image->buffer->data->Data ();
if (rect->width == image->buffer->width && rect->height == image->buffer->height && rect->x == 0 && rect->y == 0 && image->offsetX == 0 && image->offsetY == 0) {
int length = image->buffer->width * image->buffer->height;
if (color == 0 || color == 0xFFFFFFFF || (color & 0xFF == (color >> 8) & 0xFF && (color >> 8) & 0xFF == (color >> 16) & 0xFF && (color >> 16) & 0xFF == (color >> 24) & 0xFF)) {
memset ((uint8_t*)data, color & 0xFF, length * 4);
} else {
for (int i = 0; i < length; i++) {
data[i] = color;
}
uint8_t* alphaData = (uint8_t*)alphaImage->buffer->data->Data ();
PixelFormat alphaFormat = alphaImage->buffer->format;
bool alphaPremultiplied = alphaImage->buffer->premultiplied;
}
} else {
int stride = image->buffer->width;
int offset;
int rowStart = int (rect->y + image->offsetY);
int rowEnd = int (rect->y + rect->height + image->offsetY);
int columnStart = int (rect->x + image->offsetX);
int columnEnd = int (rect->x + rect->width + image->offsetX);
for (int row = rowStart; row < rowEnd; row++) {
Rectangle alphaRect = Rectangle (alphaPoint->x, alphaPoint->y, destView.width, destView.height);
ImageDataView alphaView = ImageDataView (alphaImage, &alphaRect);
int alphaPosition;
RGBA alphaPixel;
for (int column = columnStart; column < columnEnd; column++) {
for (int y = 0; y < alphaView.height; y++) {
offset = (row * stride) + (column);
data[offset] = color;
sourcePosition = sourceView.Row (y);
destPosition = destView.Row (y);
alphaPosition = alphaView.Row (y);
for (int x = 0; x < alphaView.width; x++) {
sourcePixel.ReadUInt8 (sourceData, sourcePosition, sourceFormat, sourcePremultiplied);
destPixel.ReadUInt8 (destData, destPosition, destFormat, destPremultiplied);
alphaPixel.ReadUInt8 (alphaData, alphaPosition, alphaFormat, alphaPremultiplied);
sourceAlpha = alphaPixel.a / 0xFF;
destAlpha = destPixel.a / 0xFF;
oneMinusSourceAlpha = 1 - sourceAlpha;
blendAlpha = sourceAlpha + (destAlpha * oneMinusSourceAlpha);
if (blendAlpha == 0) {
destPixel.Set (0, 0, 0, 0);
} else {
destPixel.r = __clamp[int (0.5 + (sourcePixel.r * sourceAlpha + destPixel.r * destAlpha * oneMinusSourceAlpha) / blendAlpha)];
destPixel.g = __clamp[int (0.5 + (sourcePixel.g * sourceAlpha + destPixel.g * destAlpha * oneMinusSourceAlpha) / blendAlpha)];
destPixel.b = __clamp[int (0.5 + (sourcePixel.b * sourceAlpha + destPixel.b * destAlpha * oneMinusSourceAlpha) / blendAlpha)];
destPixel.a = __clamp[int (0.5 + blendAlpha * 255.0)];
}
destPixel.WriteUInt8 (destData, destPosition, destFormat, destPremultiplied);
sourcePosition += 4;
destPosition += 4;
}
}
@@ -240,22 +243,50 @@ namespace lime {
}
void ImageDataUtil::FloodFill (Image* image, int x, int y, int color) {
void ImageDataUtil::FillRect (Image* image, Rectangle* rect, int32_t color) {
uint8_t* data = (uint8_t*)image->buffer->data->Data ();
PixelFormat format = image->buffer->format;
bool premultiplied = image->buffer->premultiplied;
int offset = (((y + image->offsetY) * (image->buffer->width * 4)) + ((x + image->offsetX) * 4));
uint8_t hitColorR = data[offset + 0];
uint8_t hitColorG = data[offset + 1];
uint8_t hitColorB = data[offset + 2];
uint8_t hitColorA = image->transparent ? data[offset + 3] : 0xFF;
ImageDataView dataView = ImageDataView (image, rect);
int row;
RGBA fillColor (color);
uint8_t r = (color >> 24) & 0xFF;
uint8_t g = (color >> 16) & 0xFF;
uint8_t b = (color >> 8) & 0xFF;
uint8_t a = image->transparent ? color & 0xFF : 0xFF;
for (int y = 0; y < dataView.height; y++) {
row = dataView.Row (y);
for (int x = 0; x < dataView.width; x++) {
fillColor.WriteUInt8 (data, row + (x * 4), format, premultiplied);
}
}
if (hitColorR == r && hitColorG == g && hitColorB == b && hitColorA == a) return;
}
void ImageDataUtil::FloodFill (Image* image, int x, int y, int32_t color) {
uint8_t* data = (uint8_t*)image->buffer->data->Data ();
PixelFormat format = image->buffer->format;
bool premultiplied = image->buffer->premultiplied;
RGBA fillColor (color);
RGBA hitColor;
hitColor.ReadUInt8 (data, ((y + image->offsetY) * (image->buffer->width * 4)) + ((x + image->offsetX) * 4), format, premultiplied);
if (!image->buffer->transparent) {
fillColor.a = 0xFF;
hitColor.a = 0xFF;
}
if (fillColor == hitColor) return;
int dx[4] = { 0, -1, 1, 0 };
int dy[4] = { -1, 0, 0, 1 };
@@ -270,6 +301,7 @@ namespace lime {
queue.push_back (y);
int curPointX, curPointY, i, nextPointX, nextPointY, nextPointOffset;
RGBA readColor;
while (queue.size () > 0) {
@@ -288,13 +320,11 @@ namespace lime {
}
nextPointOffset = (nextPointY * image->width + nextPointX) * 4;
readColor.ReadUInt8 (data, nextPointOffset, format, premultiplied);
if (data[nextPointOffset + 0] == hitColorR && data[nextPointOffset + 1] == hitColorG && data[nextPointOffset + 2] == hitColorB && data[nextPointOffset + 3] == hitColorA) {
if (readColor == hitColor) {
data[nextPointOffset + 0] = r;
data[nextPointOffset + 1] = g;
data[nextPointOffset + 2] = b;
data[nextPointOffset + 3] = a;
fillColor.WriteUInt8 (data, nextPointOffset, format, premultiplied);
queue.push_back (nextPointX);
queue.push_back (nextPointY);
@@ -313,52 +343,27 @@ namespace lime {
int length = int (rect->width * rect->height);
pixels->Resize (length * 4);
if (format == RGBA && rect->width == image->buffer->width && rect->height == image->buffer->height && rect->x == 0 && rect->y == 0) {
memcpy (pixels->Data (), image->buffer->data->Data (), image->buffer->data->Length ());
return;
}
uint8_t* data = (uint8_t*)image->buffer->data->Data ();
uint8_t* destData = (uint8_t*)pixels->Data ();
uint8_t* data = (uint8_t*)pixels->Data ();
uint8_t* srcData = (uint8_t*)image->buffer->data->Data ();
PixelFormat sourceFormat = image->buffer->format;
bool premultiplied = image->buffer->premultiplied;
int srcStride = image->buffer->Stride ();
int srcPosition = int ((rect->x * 4) + (srcStride * rect->y));
int srcRowOffset = srcStride - int (4 * rect->width);
int srcRowEnd = int (4 * (rect->x + rect->width));
ImageDataView dataView = ImageDataView (image, rect);
int position, destPosition = 0;
RGBA pixel;
if (format == ARGB) {
for (int y = 0; y < dataView.height; y++) {
for (int i = 0; i < length; i++) {
data[i * 4 + 1] = srcData[srcPosition++];
data[i * 4 + 2] = srcData[srcPosition++];
data[i * 4 + 3] = srcData[srcPosition++];
data[i * 4] = srcData[srcPosition++];
if ((srcPosition % srcStride) > srcRowEnd) {
srcPosition += srcRowOffset;
}
}
position = dataView.Row (y);
} else {
for (int i = 0; i < length; i++) {
for (int x = 0; x < dataView.width; x++) {
data[i * 4] = srcData[srcPosition++];
data[i * 4 + 1] = srcData[srcPosition++];
data[i * 4 + 2] = srcData[srcPosition++];
data[i * 4 + 3] = srcData[srcPosition++];
pixel.ReadUInt8 (data, position, sourceFormat, premultiplied);
pixel.WriteUInt8 (destData, destPosition, format, false);
if ((srcPosition % srcStride) > srcRowEnd) {
srcPosition += srcRowOffset;
}
position += 4;
destPosition += 4;
}
@@ -369,31 +374,39 @@ namespace lime {
void ImageDataUtil::Merge (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int redMultiplier, int greenMultiplier, int blueMultiplier, int alphaMultiplier) {
int rowOffset = int (destPoint->y + image->offsetY - sourceRect->y - sourceImage->offsetY);
int columnOffset = int (destPoint->x + image->offsetX - sourceRect->x - sourceImage->offsetY);
ImageDataView sourceView = ImageDataView (sourceImage, sourceRect);
Rectangle destRect = Rectangle (destPoint->x, destPoint->y, sourceView.width, sourceView.height);
ImageDataView destView = ImageDataView (image, &destRect);
uint8_t* sourceData = (uint8_t*)sourceImage->buffer->data->Data ();
int sourceStride = sourceImage->buffer->Stride ();
int sourceOffset = 0;
uint8_t* destData = (uint8_t*)image->buffer->data->Data ();
PixelFormat sourceFormat = sourceImage->buffer->format;
PixelFormat destFormat = image->buffer->format;
bool sourcePremultiplied = sourceImage->buffer->premultiplied;
bool destPremultiplied = image->buffer->premultiplied;
uint8_t* data = (uint8_t*)image->buffer->data->Data ();
int stride = image->buffer->Stride ();
int offset = 0;
int sourcePosition, destPosition;
RGBA sourcePixel, destPixel;
int rowEnd = int (sourceRect->y + sourceRect->height + sourceImage->offsetY);
int columnEnd = int (sourceRect->x + sourceRect->width + sourceImage->offsetX);
for (int row = int (sourceRect->y + sourceImage->offsetY); row < rowEnd; row++) {
for (int y = 0; y < destView.height; y++) {
for (int column = int (sourceRect->x + sourceImage->offsetX); column < columnEnd; column++) {
sourcePosition = sourceView.Row (y);
destPosition = destView.Row (y);
for (int x = 0; x < destView.width; x++) {
sourceOffset = (row * sourceStride) + (column * 4);
offset = ((row + rowOffset) * stride) + ((column + columnOffset) * 4);
sourcePixel.ReadUInt8 (sourceData, sourcePosition, sourceFormat, sourcePremultiplied);
destPixel.ReadUInt8 (destData, destPosition, destFormat, destPremultiplied);
data[offset] = int (((sourceData[offset] * redMultiplier) + (data[offset] * (256 - redMultiplier))) / 256);
data[offset + 1] = int (((sourceData[offset + 1] * greenMultiplier) + (data[offset + 1] * (256 - greenMultiplier))) / 256);
data[offset + 2] = int (((sourceData[offset + 2] * blueMultiplier) + (data[offset + 2] * (256 - blueMultiplier))) / 256);
data[offset + 3] = int (((sourceData[offset + 3] * alphaMultiplier) + (data[offset + 3] * (256 - alphaMultiplier))) / 256);
destPixel.r = int (((sourcePixel.r * redMultiplier) + (destPixel.r * (256 - redMultiplier))) / 256);
destPixel.g = int (((sourcePixel.g * greenMultiplier) + (destPixel.g * (256 - greenMultiplier))) / 256);
destPixel.b = int (((sourcePixel.b * blueMultiplier) + (destPixel.b * (256 - blueMultiplier))) / 256);
destPixel.a = int (((sourcePixel.a * alphaMultiplier) + (destPixel.a * (256 - alphaMultiplier))) / 256);
destPixel.WriteUInt8 (destData, destPosition, destFormat, destPremultiplied);
sourcePosition += 4;
destPosition += 4;
}
@@ -404,17 +417,15 @@ namespace lime {
void ImageDataUtil::MultiplyAlpha (Image* image) {
int a16 = 0;
int length = image->buffer->data->Length () / 4;
PixelFormat format = image->buffer->format;
uint8_t* data = (uint8_t*)image->buffer->data->Data ();
int length = int (image->buffer->data->Length () / 4);
RGBA pixel;
for (int i = 0; i < length; i++) {
a16 = __alpha16[data[3]];
data[0] = (data[0] * a16) >> 16;
data[1] = (data[1] * a16) >> 16;
data[2] = (data[2] * a16) >> 16;
data += 4;
pixel.ReadUInt8 (data, i * 4, format, false);
pixel.WriteUInt8 (data, i * 4, format, true);
}
@@ -487,7 +498,7 @@ namespace lime {
switch (image->buffer->format) {
case RGBA:
case RGBA32:
r1 = 0;
g1 = 1;
@@ -495,7 +506,7 @@ namespace lime {
a1 = 3;
break;
case ARGB:
case ARGB32:
r1 = 1;
g1 = 2;
@@ -503,7 +514,7 @@ namespace lime {
a1 = 0;
break;
case BGRA:
case BGRA32:
r1 = 2;
g1 = 1;
@@ -515,7 +526,7 @@ namespace lime {
switch (format) {
case RGBA:
case RGBA32:
r2 = 0;
g2 = 1;
@@ -523,7 +534,7 @@ namespace lime {
a2 = 3;
break;
case ARGB:
case ARGB32:
r2 = 1;
g2 = 2;
@@ -531,7 +542,7 @@ namespace lime {
a2 = 0;
break;
case BGRA:
case BGRA32:
r2 = 2;
g2 = 1;
@@ -564,61 +575,29 @@ namespace lime {
void ImageDataUtil::SetPixels (Image* image, Rectangle* rect, Bytes* bytes, PixelFormat format) {
if (format == RGBA && rect->width == image->buffer->width && rect->height == image->buffer->height && rect->x == 0 && rect->y == 0) {
memcpy (image->buffer->data->Data (), bytes->Data (), bytes->Length ());
return;
}
uint8_t* data = (uint8_t*)image->buffer->data->Data ();
PixelFormat sourceFormat = image->buffer->format;
bool premultiplied = image->buffer->premultiplied;
ImageDataView dataView = ImageDataView (image, rect);
int row;
RGBA pixel;
int offset = int (image->buffer->width * (rect->y + image->offsetX) + (rect->x + image->offsetY));
int boundR = int ((rect->x + rect->width + image->offsetX));
int width = image->buffer->width;
int color;
uint8_t* byteArray = (uint8_t*)bytes->Data ();
int srcPosition = 0;
if (format == ARGB) {
bool transparent = image->buffer->transparent;
for (int y = 0; y < dataView.height; y++) {
int pos = offset * 4;
int len = int (rect->width * rect->height * 4);
uint8_t* data = (uint8_t*)image->buffer->data->Data ();
uint8_t* byteArray = (uint8_t*)bytes->Data ();
row = dataView.Row (y);
for (int i = 0; i < len; i += 4) {
for (int x = 0; x < dataView.width; x++) {
pixel.ReadUInt8 (byteArray, srcPosition, format, false);
if (!transparent) pixel.a = 0xFF;
pixel.WriteUInt8 (data, row + (x * 4), sourceFormat, premultiplied);
if (((pos) % (width * 4)) >= boundR * 4) {
pos += (width - boundR) * 4;
}
data[pos] = byteArray[i + 1];
data[pos + 1] = byteArray[i + 2];
data[pos + 2] = byteArray[i + 3];
data[pos + 3] = byteArray[i];
pos += 4;
}
} else {
int pos = offset;
int len = int (rect->width * rect->height);
int* data = (int*)image->buffer->data->Data ();
int* byteArray = (int*)bytes->Data ();
// TODO: memcpy rows at once
for (int i = 0; i < len; i++) {
if (((pos) % (width)) >= boundR) {
pos += (width - boundR);
}
data[pos] = byteArray[i];
pos++;
srcPosition += 4;
}
@@ -629,28 +608,64 @@ namespace lime {
void ImageDataUtil::UnmultiplyAlpha (Image* image) {
int length = image->buffer->data->Length () / 4;
PixelFormat format = image->buffer->format;
uint8_t* data = (uint8_t*)image->buffer->data->Data ();
int unmultiply;
uint8_t a;
int length = int (image->buffer->data->Length () / 4);
RGBA pixel;
for (int i = 0; i < length; i++) {
a = data[3];
if (a != 0) {
unmultiply = 255.0 / a;
data[0] = __clamp[data[0] * unmultiply];
data[1] = __clamp[data[1] * unmultiply];
data[2] = __clamp[data[2] * unmultiply];
}
pixel.ReadUInt8 (data, i * 4, format, true);
pixel.WriteUInt8 (data, i * 4, format, false);
}
}
ImageDataView::ImageDataView (Image* image, Rectangle* rect) {
this->image = image;
if (rect->x < 0) rect->x = 0;
if (rect->y < 0) rect->y = 0;
if (rect->x + rect->width > image->width) rect->width = image->width - rect->x;
if (rect->y + rect->height > image->height) rect->height = image->height - rect->y;
if (rect->width < 0) rect->width = 0;
if (rect->height < 0) rect->height = 0;
this->rect = rect;
stride = image->buffer->Stride ();
x = ceil (this->rect->x);
y = ceil (this->rect->y);
width = floor (this->rect->width);
height = floor (this->rect->height);
offset = (stride * (this->y + image->offsetY)) + ((this->x + image->offsetX) * 4);
}
void ImageDataView::Clip (int x, int y, int width, int height) {
rect->Contract (x, y, width, height);
this->x = ceil (rect->x);
this->y = ceil (rect->y);
this->width = floor (rect->width);
this->height = floor (rect->height);
offset = (stride * (this->y + image->offsetY)) + ((this->x + image->offsetX) * 4);
}
inline int ImageDataView::Row (int y) {
return offset + stride * y;
}
}

View File

@@ -57,67 +57,111 @@ namespace lime {
}
float ColorMatrix::GetAlphaMultiplier () {
float inline ColorMatrix::GetAlphaMultiplier () {
return data[18];
}
float ColorMatrix::GetAlphaOffset () {
float inline ColorMatrix::GetAlphaOffset () {
return data[19] * 255;
}
float ColorMatrix::GetBlueMultiplier () {
void ColorMatrix::GetAlphaTable (unsigned char* table) {
GetDataTable (table, GetAlphaMultiplier (), GetAlphaOffset ());
}
float inline ColorMatrix::GetBlueMultiplier () {
return data[12];
}
float ColorMatrix::GetBlueOffset () {
float inline ColorMatrix::GetBlueOffset () {
return data[14] * 255;
}
int ColorMatrix::GetColor () {
void ColorMatrix::GetBlueTable (unsigned char* table) {
GetDataTable (table, GetBlueMultiplier (), GetBlueOffset ());
}
int32_t inline ColorMatrix::GetColor () {
return ((int (GetRedOffset ()) << 16) | (int (GetGreenOffset ()) << 8) | int (GetBlueOffset ()));
}
float ColorMatrix::GetGreenMultiplier () {
void inline ColorMatrix::GetDataTable (unsigned char* table, float multiplier, float offset) {
int32_t value;
for (int i = 0; i < 256; i++) {
value = (int)(i * multiplier + offset);
if (value > 0xFF) value = 0xFF;
if (value < 0) value = 0;
table[i] = value;
}
}
float inline ColorMatrix::GetGreenMultiplier () {
return data[6];
}
float ColorMatrix::GetGreenOffset () {
float inline ColorMatrix::GetGreenOffset () {
return data[9] * 255;
}
float ColorMatrix::GetRedMultiplier () {
void ColorMatrix::GetGreenTable (unsigned char* table) {
GetDataTable (table, GetGreenMultiplier (), GetGreenOffset ());
}
float inline ColorMatrix::GetRedMultiplier () {
return data[0];
}
float ColorMatrix::GetRedOffset () {
float inline ColorMatrix::GetRedOffset () {
return data[4] * 255;
}
void ColorMatrix::GetRedTable (unsigned char* table) {
GetDataTable (table, GetRedMultiplier (), GetRedOffset ());
}
}

View File

@@ -51,4 +51,23 @@ namespace lime {
}
void Rectangle::Contract (double x, double y, double width, double height) {
if (this->width == 0 && this->height == 0) {
return;
}
//double cacheRight = this->x + this->width;
//double cacheBottom = this->y + this->height;
if (this->x < x) this->x = x;
if (this->y < y) this->y = y;
if (this->x + this->width > x + width) this->width = x + width - this->x;
if (this->y + this->height > y + height) this->height = y + height - this->y;
}
}