mirror of
https://github.com/raysan5/raylib.git
synced 2026-10-10 19:51:55 -04:00
Compare commits
7 Commits
6ecf21f700
...
d2d6fe6ef9
| Author | SHA1 | Date | |
|---|---|---|---|
| d2d6fe6ef9 | |||
| 47dea9b452 | |||
| 002f0310f3 | |||
| 2ca7349a0c | |||
| 3b028f0a17 | |||
| 83b9c17366 | |||
| 5496945d8b |
40
src/rtext.c
40
src/rtext.c
@ -2811,6 +2811,7 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, c
|
||||
char buffer[MAX_BUFFER_SIZE] = { 0 };
|
||||
|
||||
GlyphInfo *glyphs = NULL;
|
||||
GlyphInfo *outGlyphPtr = NULL; // Pointer to output glyph info (NULL if not set)
|
||||
bool internalCodepoints = false;
|
||||
|
||||
int totalReadBytes = 0; // Data bytes read (total)
|
||||
@ -2839,12 +2840,11 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, c
|
||||
int charDWidthX = 0; // Character advance X
|
||||
int charDWidthY = 0; // Character advance Y (unused)
|
||||
|
||||
int *requiredCodepoints = (int *)RL_MALLOC(codepointCount*sizeof(int));
|
||||
|
||||
if (fileData == NULL) return glyphs;
|
||||
|
||||
// In case no chars count provided, default to 95
|
||||
codepointCount = (codepointCount > 0)? codepointCount : 95;
|
||||
int *requiredCodepoints = (int *)RL_MALLOC(codepointCount*sizeof(int));
|
||||
|
||||
if (codepoints == NULL)
|
||||
{
|
||||
@ -2880,11 +2880,11 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, c
|
||||
|
||||
if (charBitmapStarted)
|
||||
{
|
||||
if (glyphs != NULL)
|
||||
if (outGlyphPtr != NULL)
|
||||
{
|
||||
int pixelY = charBitmapNextRow++;
|
||||
|
||||
if (pixelY >= glyphs->image.height) break;
|
||||
if (pixelY >= outGlyphPtr->image.height) break;
|
||||
|
||||
for (int x = 0; x < readBytes; x++)
|
||||
{
|
||||
@ -2894,9 +2894,9 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, c
|
||||
{
|
||||
int pixelX = ((x*4) + bitX);
|
||||
|
||||
if (pixelX >= glyphs->image.width) break;
|
||||
if (pixelX >= outGlyphPtr->image.width) break;
|
||||
|
||||
if ((byte & (8 >> bitX)) > 0) ((unsigned char *)glyphs->image.data)[(pixelY*glyphs->image.width) + pixelX] = 255;
|
||||
if ((byte & (8 >> bitX)) > 0) ((unsigned char *)outGlyphPtr->image.data)[(pixelY*outGlyphPtr->image.width) + pixelX] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2928,30 +2928,30 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, c
|
||||
if (strstr(buffer, "BITMAP") != NULL)
|
||||
{
|
||||
// Search for glyph index in codepoints
|
||||
glyphs = NULL;
|
||||
outGlyphPtr = NULL;
|
||||
|
||||
for (int index = 0; index < codepointCount; index++)
|
||||
{
|
||||
if (requiredCodepoints[index] == charEncoding)
|
||||
{
|
||||
glyphs = &glyphs[index];
|
||||
outGlyphPtr = &glyphs[index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Init glyph info
|
||||
if (glyphs != NULL)
|
||||
if (outGlyphPtr != NULL)
|
||||
{
|
||||
glyphs->value = charEncoding;
|
||||
glyphs->offsetX = charBBxoff0 + fontBByoff0;
|
||||
glyphs->offsetY = fontBBh - (charBBh + charBByoff0 + fontBByoff0 + fontAscent);
|
||||
glyphs->advanceX = charDWidthX;
|
||||
outGlyphPtr->value = charEncoding;
|
||||
outGlyphPtr->offsetX = charBBxoff0 + fontBByoff0;
|
||||
outGlyphPtr->offsetY = fontBBh - (charBBh + charBByoff0 + fontBByoff0 + fontAscent);
|
||||
outGlyphPtr->advanceX = charDWidthX;
|
||||
|
||||
glyphs->image.data = RL_CALLOC(charBBw*charBBh, 1);
|
||||
glyphs->image.width = charBBw;
|
||||
glyphs->image.height = charBBh;
|
||||
glyphs->image.mipmaps = 1;
|
||||
glyphs->image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
|
||||
outGlyphPtr->image.data = RL_CALLOC(charBBw*charBBh, 1);
|
||||
outGlyphPtr->image.width = charBBw;
|
||||
outGlyphPtr->image.height = charBBh;
|
||||
outGlyphPtr->image.mipmaps = 1;
|
||||
outGlyphPtr->image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
|
||||
}
|
||||
|
||||
charBitmapStarted = true;
|
||||
@ -3002,14 +3002,14 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, c
|
||||
{
|
||||
charStarted = true;
|
||||
charEncoding = -1;
|
||||
glyphs = NULL;
|
||||
outGlyphPtr = NULL;
|
||||
charBBw = 0;
|
||||
charBBh = 0;
|
||||
charBBxoff0 = 0;
|
||||
charBByoff0 = 0;
|
||||
charDWidthX = 0;
|
||||
charDWidthY = 0;
|
||||
glyphs = NULL;
|
||||
outGlyphPtr = NULL;
|
||||
charBitmapStarted = false;
|
||||
charBitmapNextRow = 0;
|
||||
continue;
|
||||
|
||||
178
src/rtextures.c
178
src/rtextures.c
@ -1592,7 +1592,7 @@ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Co
|
||||
TRACELOG(LOG_INFO, "IMAGE: Text scaled by factor: %f", scaleFactor);
|
||||
|
||||
// Using nearest-neighbor scaling algorithm for default font
|
||||
// TODO: Support selection of preferred scaling mechanism, use flag?
|
||||
// TODO: Support other scaling mechanism, use flag?
|
||||
if (font.texture.id == GetFontDefault().texture.id) ImageResizeNN(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor));
|
||||
else ImageResize(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor));
|
||||
}
|
||||
@ -3902,7 +3902,82 @@ void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color)
|
||||
// Draw a color-filled rectangle with pro parameters within and image
|
||||
void ImageDrawRectanglePro(Image *dst, Rectangle rec, Vector2 origin, float rotation, Color color)
|
||||
{
|
||||
// TODO: NEW: Implement ImageDrawRectanglePro()
|
||||
// Security checks to avoid program crash
|
||||
if ((dst == NULL) || (dst->data == NULL) || (rec.width <= 0) || (rec.height <= 0)) return;
|
||||
|
||||
float cosAngle = cosf(rotation*DEG2RAD);
|
||||
float sinAngle = sinf(rotation*DEG2RAD);
|
||||
|
||||
// Rotation origin in world/image coordinates
|
||||
float ox = rec.x + origin.x;
|
||||
float oy = rec.y + origin.y;
|
||||
|
||||
// Rectangle corners relative to rotation origin
|
||||
float x1 = -origin.x;
|
||||
float y1 = -origin.y;
|
||||
|
||||
float x2 = rec.width - origin.x;
|
||||
float y2 = rec.height - origin.y;
|
||||
|
||||
// Rotate the four corners to calculate the bounding box
|
||||
float cornersX[4] = { x1, x2, x2, x1 };
|
||||
float cornersY[4] = { y1, y1, y2, y2 };
|
||||
|
||||
float minX = 65536;
|
||||
float minY = 65536;
|
||||
float maxX = -65536;
|
||||
float maxY = -65536;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
float rx = cornersX[i]*cosAngle - cornersY[i]*sinAngle;
|
||||
float ry = cornersX[i]*sinAngle + cornersY[i]*cosAngle;
|
||||
|
||||
rx += ox;
|
||||
ry += oy;
|
||||
|
||||
if (rx < minX) minX = rx;
|
||||
if (ry < minY) minY = ry;
|
||||
if (rx > maxX) maxX = rx;
|
||||
if (ry > maxY) maxY = ry;
|
||||
}
|
||||
|
||||
// Convert bounding box to integer pixel bounds
|
||||
int x0 = (int)floorf(minX);
|
||||
int y0 = (int)floorf(minY);
|
||||
int xEnd = (int)ceilf(maxX);
|
||||
int yEnd = (int)ceilf(maxY);
|
||||
|
||||
// Limit drawing to image bounds
|
||||
if (x0 < 0) x0 = 0;
|
||||
if (y0 < 0) y0 = 0;
|
||||
if (xEnd > dst->width) xEnd = dst->width;
|
||||
if (yEnd > dst->height) yEnd = dst->height;
|
||||
|
||||
// Safety check
|
||||
if ((x0 >= xEnd) || (y0 >= yEnd)) return;
|
||||
|
||||
for (int y = y0; y < yEnd; y++)
|
||||
{
|
||||
for (int x = x0; x < xEnd; x++)
|
||||
{
|
||||
// Pixel center in world coordinates
|
||||
float px = x + 0.5f - ox;
|
||||
float py = y + 0.5f - oy;
|
||||
|
||||
// Inverse-rotate pixel into rectangle local space
|
||||
float localX = px*cosAngle + py*sinAngle;
|
||||
float localY = -px*sinAngle + py*cosAngle;
|
||||
|
||||
// Check whether pixel lies inside the rectangle
|
||||
if ((localX >= -origin.x) && (localX < (rec.width - origin.x)) &&
|
||||
(localY >= -origin.y) && (localY < (rec.height - origin.y)))
|
||||
{
|
||||
// NOTE: Pixel format conversion managed by function
|
||||
ImageDrawPixel(dst, x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw rectangle lines within an image
|
||||
@ -4080,7 +4155,7 @@ void ImageDrawCircleGradient(Image *dst, Vector2 center, float radius, Color inn
|
||||
(unsigned char)(inner.a + (outer.a - inner.a)*t)
|
||||
};
|
||||
|
||||
// NOTE: Pixel format conversion managed by ImageDrawPixel()
|
||||
// NOTE: Pixel format conversion managed by function
|
||||
ImageDrawPixel(dst, x, y, color);
|
||||
}
|
||||
}
|
||||
@ -4095,9 +4170,103 @@ void ImageDrawImage(Image *dst, Image src, int posX, int posY, Color tint)
|
||||
}
|
||||
|
||||
// Draw an image with scaling and rotation within an image
|
||||
// NOTE: Rotation applied from top-left corner origin
|
||||
void ImageDrawImageEx(Image *dst, Image src, Vector2 position, float rotation, float scale, Color tint)
|
||||
{
|
||||
// TODO: NEW: Implement ImageDrawImageEx()
|
||||
// Security checks to avoid program crash
|
||||
if ((dst == NULL) || (dst->data == NULL) || (dst->width <= 0) || (dst->height <= 0) || (src.width <= 0) || (src.height <= 0)) return;
|
||||
|
||||
float cosA = cosf(rotation*DEG2RAD);
|
||||
float sinA = sinf(rotation*DEG2RAD);
|
||||
|
||||
// Rotate around the source image top-left corner
|
||||
float cornersX[4] = { 0.0f, src.width*scale, src.width*scale, 0.0f };
|
||||
float cornersY[4] = { 0.0f, 0.0f, src.height*scale, src.height*scale };
|
||||
|
||||
float minX = 65536;
|
||||
float minY = 65536;
|
||||
float maxX = -65536;
|
||||
float maxY = -65536;
|
||||
|
||||
// Calculate the rotated bounding box
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
float rx = cornersX[i]*cosA - cornersY[i]*sinA;
|
||||
float ry = cornersX[i]*sinA + cornersY[i]*cosA;
|
||||
|
||||
rx += position.x;
|
||||
ry += position.y;
|
||||
|
||||
if (rx < minX) minX = rx;
|
||||
if (ry < minY) minY = ry;
|
||||
if (rx > maxX) maxX = rx;
|
||||
if (ry > maxY) maxY = ry;
|
||||
}
|
||||
|
||||
int x0 = (int)floorf(minX);
|
||||
int y0 = (int)floorf(minY);
|
||||
int x1 = (int)ceilf(maxX);
|
||||
int y1 = (int)ceilf(maxY);
|
||||
|
||||
// Limit drawing to destination bounds
|
||||
if (x0 < 0) x0 = 0;
|
||||
if (y0 < 0) y0 = 0;
|
||||
if (x1 > dst->width) x1 = dst->width;
|
||||
if (y1 > dst->height) y1 = dst->height;
|
||||
|
||||
// Safety check
|
||||
if ((x0 >= x1) || (y0 >= y1)) return;
|
||||
|
||||
for (int y = y0; y < y1; y++)
|
||||
{
|
||||
for (int x = x0; x < x1; x++)
|
||||
{
|
||||
// Destination pixel center relative to image position
|
||||
float dx = (x + 0.5f) - position.x;
|
||||
float dy = (y + 0.5f) - position.y;
|
||||
|
||||
// Inverse-rotate into the scaled source space
|
||||
float sx = dx*cosA + dy*sinA;
|
||||
float sy = -dx*sinA + dy*cosA;
|
||||
|
||||
// Revert scaling
|
||||
sx /= scale;
|
||||
sy /= scale;
|
||||
|
||||
// Skip pixels outside the source image
|
||||
if ((sx < 0.0f) || (sy < 0.0f) || (sx >= src.width) || (sy >= src.height)) continue;
|
||||
|
||||
// Nearest-neighbor source sampling
|
||||
int srcX = (int)sx;
|
||||
int srcY = (int)sy;
|
||||
|
||||
Color srcColor = GetImageColor(src, srcX, srcY);
|
||||
|
||||
// Apply tint
|
||||
srcColor.r = (unsigned char)(srcColor.r*tint.r/255.0f);
|
||||
srcColor.g = (unsigned char)(srcColor.g*tint.g/255.0f);
|
||||
srcColor.b = (unsigned char)(srcColor.b*tint.b/255.0f);
|
||||
srcColor.a = (unsigned char)(srcColor.a*tint.a/255.0f);
|
||||
|
||||
// Skip fully transparent pixels
|
||||
if (srcColor.a == 0) continue;
|
||||
|
||||
// Read destination pixel for alpha blending
|
||||
Color dstColor = GetImageColor(*dst, x, y);
|
||||
|
||||
unsigned int alpha = srcColor.a;
|
||||
unsigned int invA = 255 - alpha;
|
||||
|
||||
Color out = {
|
||||
(unsigned char)((srcColor.r*alpha + dstColor.r*invA)/255), // red
|
||||
(unsigned char)((srcColor.g*alpha + dstColor.g*invA)/255), // green
|
||||
(unsigned char)((srcColor.b*alpha + dstColor.b*invA)/255), // blue
|
||||
(unsigned char)(alpha + (dstColor.a*invA)/255) // alpha
|
||||
};
|
||||
|
||||
ImageDrawPixel(dst, x, y, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a part of an image defined by a rectangle within an image
|
||||
@ -4682,6 +4851,7 @@ void DrawTextureV(Texture2D texture, Vector2 position, Color tint)
|
||||
}
|
||||
|
||||
// Draw a texture with rotation and scale
|
||||
// NOTE: Rotation applied from top-left corner origin
|
||||
void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint)
|
||||
{
|
||||
Rectangle srcrec = { 0.0f, 0.0f, (float)texture.width, (float)texture.height };
|
||||
|
||||
Reference in New Issue
Block a user