37 if (edgeA->
x < edgeB->
x)
41 else if (edgeA->
x > edgeB->
x)
50 if (draw ==
NULL || points ==
NULL || pointCount < 3)
60 for (
uint64_t i = 0; i < pointCount; i++)
62 minY =
MIN(minY, points[i].
y);
63 maxY =
MAX(maxY, points[i].
y);
64 minX =
MIN(minX, points[i].
x);
65 maxX =
MAX(maxX, points[i].
x);
70 for (
uint64_t i = 0; i < pointCount; i++)
73 point_t p2 = points[(i + 1) % pointCount];
78 edge_t* edge = &edges[edgeCount++];
84 edge->
invSlope = (double)(p2.
x - p1.
x) / (double)(p2.
y - p1.
y);
91 edge->
invSlope = (double)(p1.
x - p2.
x) / (double)(p1.
y - p2.
y);
95 const double samples[4][2] = {{0.125, 0.375}, {0.375, 0.125}, {0.625, 0.875}, {0.875, 0.625}};
96 const int sampleCount = 4;
98 edge_t* activeEdges[pointCount];
103 for (
uint64_t i = 0; i < edgeCount; i++)
105 if (edges[i].yMin ==
y)
107 activeEdges[activeEdgeCount++] = &edges[i];
111 for (
uint64_t i = 0; i < activeEdgeCount; i++)
113 if (activeEdges[i]->yMax <=
y)
115 activeEdges[i] = activeEdges[--activeEdgeCount];
120 if (activeEdgeCount < 2)
138 for (
int64_t x = scanMinX;
x <= scanMaxX;
x++)
140 int samplesInside = 0;
142 for (
int s = 0; s < sampleCount; s++)
144 double sampleX =
x + samples[s][0];
145 double sampleY =
y + samples[s][1];
153 if (samplesInside == 0)
157 else if (samplesInside == sampleCount)
164 uint8_t newAlpha = (originalAlpha * samplesInside) / sampleCount;
172 for (
uint64_t i = 0; i < activeEdgeCount; i++)
174 activeEdges[i]->
x += activeEdges[i]->
invSlope;
192 double angle =
atan2((
double)(fitEnd.
y - fitStart.
y), (
double)(fitEnd.
x - fitStart.
x));
193 double halfThickness = (double)thickness / 2.0;
194 double sinAngle =
sin(angle +
M_PI_2) * halfThickness;
195 double cosAngle =
cos(angle +
M_PI_2) * halfThickness;
206 if (draw ==
NULL || rect ==
NULL || width == 0)
217 .right = fitRect.
left + width,
218 .bottom = fitRect.
bottom - width,
225 .right = fitRect.
right - width,
226 .bottom = fitRect.
top + width,
232 .top = fitRect.
top + width,
233 .right = fitRect.
right,
240 .top = fitRect.
bottom - width,
241 .right = fitRect.
right - width,
244 draw_rect(draw, &bottomRect, background);
250 pixel_t color =
x +
y < width - 1 ? foreground : background;
261 if (draw ==
NULL || rect ==
NULL || length == 0 || width <= 0)
276 for (
int32_t w = 0; w < width; w++)
284 if (inPattern < length)
298 if (inPattern < length)
306 for (
int32_t w = 0; w < width; w++)
313 uint32_t inPattern = (
y - fitRect.
top - width) % totalLength;
314 if (inPattern < length)
327 uint32_t inPattern = (
y - fitRect.
top - width) % totalLength;
328 if (inPattern < length)
341 if (draw ==
NULL || rect ==
NULL || width == 0)
351 .top = fitRect.
top + width - width / 2,
352 .right = fitRect.
left + width,
353 .bottom = fitRect.
bottom - width + width / 2,
358 .
left = fitRect.
left + width - width / 2,
360 .right = fitRect.
right - width + width / 2,
361 .bottom = fitRect.
top + width,
367 .top = fitRect.
top + width - width / 2,
368 .right = fitRect.
right,
369 .bottom = fitRect.
bottom - width + width / 2,
374 .
left = fitRect.
left + width - width / 2,
375 .top = fitRect.
bottom - width,
376 .right = fitRect.
right - width + width / 2,
407 factorNum = (
y - fitRect.
top);
408 factorDenom = height;
413 factorNum = (
x - fitRect.
left);
419 factorNum = (
x - fitRect.
left) + (
y - fitRect.
top);
420 factorDenom = width + height;
449 red =
CLAMP(0, 255, red);
450 green =
CLAMP(0, 255, green);
451 blue =
CLAMP(0, 255, blue);
472 if (width <= 0 || height <= 0)
517 if (width <= 0 || height <= 0)
593 if (draw ==
NULL ||
string ==
NULL || point ==
NULL || length == 0)
608 for (
uint64_t i = 0; i < length; i++)
637 aligned->
x = rect->
left;
646 aligned->
x = rect->
left;
653 aligned->
y = rect->
top;
656 aligned->
y = rect->
top + (
RECT_HEIGHT(rect) / 2) - (visualTextHeight / 2);
662 aligned->
y = rect->
top;
670 if (draw ==
NULL || rect ==
NULL || text ==
NULL || *text ==
'\0')
684 if (textWidth <= maxWidth)
688 draw_string(draw, font, &startPoint, pixel, text, originalTextLen);
692 const char* ellipsis =
"...";
695 const char* drawText = text;
697 const char* drawEllipsis =
NULL;
699 if (ellipsisWidth <= maxWidth)
704 for (
uint64_t i = 0; i < originalTextLen; ++i)
707 if (i < originalTextLen - 1)
712 if (currentContentWidth + charWidth + ellipsisWidth <= maxWidth)
714 currentContentWidth += charWidth;
724 drawTextLen = fittedOriginalLen;
725 drawEllipsis = ellipsis;
740 if (currentContentWidth + charWidth <= maxWidth)
742 currentContentWidth += charWidth;
752 drawTextLen = fittedEllipsisLen;
757 if (drawEllipsis !=
NULL)
763 totalWidth =
font_width(font, drawText, drawTextLen);
772 startPoint.
x = rect->
left;
781 startPoint.
x = rect->
left;
788 startPoint.
y = rect->
top;
791 startPoint.
y = rect->
top + (
RECT_HEIGHT(rect) / 2) - (visualTextHeight / 2);
797 startPoint.
y = rect->
top;
801 draw_string(draw, font, &startPoint, pixel, drawText, drawTextLen);
803 if (drawEllipsis !=
NULL)
807 draw_string(draw, font, &ellipsisStartPoint, pixel, drawEllipsis, 3);
813 pixel_t pixel,
const char* text)
815 if (draw ==
NULL || rect ==
NULL || text ==
NULL || *text ==
'\0')
832 const char* textPtr = text;
834 while (*textPtr !=
'\0')
836 const char* lineStart = textPtr;
837 const char* lineEnd = textPtr;
838 const char* lastSpace =
NULL;
841 while (*textPtr !=
'\0' && *textPtr !=
'\n')
853 if (*(textPtr + 1) !=
'\0' && *(textPtr + 1) !=
'\n')
858 if (currentWidth > maxWidth && lastSpace !=
NULL)
868 if (*textPtr ==
'\n' || *textPtr ==
'\0')
872 else if (lastSpace ==
NULL)
879 if (*textPtr ==
'\n')
883 else if (*textPtr !=
'\0')
885 textPtr = lineEnd + 1;
889 int32_t totalTextHeight = lineCount * lineHeight;
895 startY = fitRect.
top;
898 startY = fitRect.
top + (
RECT_HEIGHT(&fitRect) / 2) - (totalTextHeight / 2);
904 startY = fitRect.
top;
911 while (*textPtr !=
'\0' && currentY + lineHeight <= fitRect.
bottom)
913 const char* lineStart = textPtr;
914 const char* lineEnd = textPtr;
915 const char* lastSpace =
NULL;
918 while (*textPtr !=
'\0' && *textPtr !=
'\n')
930 if (*(textPtr + 1) !=
'\0' && *(textPtr + 1) !=
'\n')
935 if (currentWidth > maxWidth && lastSpace !=
NULL)
945 if (*textPtr ==
'\n' || *textPtr ==
'\0')
949 else if (lastSpace ==
NULL)
954 int64_t lineLength = lineEnd - lineStart;
961 lineX = fitRect.
left;
970 lineX = fitRect.
left;
974 point_t linePos = {.
x = lineX, .y = currentY};
975 draw_string(draw, font, &linePos, pixel, lineStart, lineLength);
977 currentY += lineHeight;
979 if (*textPtr ==
'\n')
983 else if (*textPtr !=
'\0')
985 textPtr = lineEnd + 1;
994 if (draw ==
NULL || rect ==
NULL || width == 0)
999 draw_frame(draw, rect, width / 2, background, foreground);
1001 rect_t innerRect = *rect;
1003 draw_frame(draw, &innerRect, width / 2, foreground, background);
1024 .right = fitRect.
left + width / 2,
1025 .bottom = fitRect.
bottom};
1028 .right = fitRect.
right,
1029 .bottom = fitRect.
bottom};
1041 .right = fitRect.
right,
1042 .bottom = fitRect.
top + height / 2};
1044 .top = fitRect.
top + height / 2,
1045 .right = fitRect.
right,
1046 .bottom = fitRect.
bottom};
static void draw_grf_char(drawable_t *draw, const font_t *font, const point_t *point, uint8_t chr, pixel_t pixel)
static void draw_calculate_aligned_text_pos(const rect_t *rect, const font_t *font, const char *string, uint64_t length, align_t xAlign, align_t yAlign, point_t *aligned)
static int edge_compare(const void *a, const void *b)
uint64_t font_width(const font_t *font, const char *string, uint64_t length)
int16_t font_kerning_offset(const font_t *font, char firstChar, char secondChar)
font_t * font_default(display_t *disp)
void draw_text_multiline(drawable_t *draw, const rect_t *rect, const font_t *font, align_t xAlign, align_t yAlign, pixel_t pixel, const char *text)
Draw multiline text to a drawable.
void draw_line(drawable_t *draw, const point_t *start, const point_t *end, pixel_t pixel, uint32_t thickness)
Draw a line between two points.
void draw_transfer_blend(drawable_t *dest, drawable_t *src, const rect_t *destRect, const point_t *srcPoint)
Transfer pixels from one drawable to another with alpha blending.
void draw_polygon(drawable_t *draw, const point_t *points, uint64_t pointCount, pixel_t pixel)
Draw a filled polygon.
void draw_gradient(drawable_t *draw, const rect_t *rect, pixel_t start, pixel_t end, direction_t direction, bool shouldAddNoise)
Draw a gradient filled rectangle.
void draw_string(drawable_t *draw, const font_t *font, const point_t *point, pixel_t pixel, const char *string, uint64_t length)
Draw a string.
void draw_image_blend(drawable_t *draw, image_t *image, const rect_t *destRect, const point_t *srcPoint)
Draw an image with alpha blending.
void draw_rect(drawable_t *draw, const rect_t *rect, pixel_t pixel)
Draw a filled rectangle.
void draw_ridge(drawable_t *draw, const rect_t *rect, uint64_t width, pixel_t foreground, pixel_t background)
Draw a ridge effect.
void draw_image(drawable_t *draw, image_t *image, const rect_t *destRect, const point_t *srcPoint)
Draw an image,.
void draw_separator(drawable_t *draw, const rect_t *rect, pixel_t highlight, pixel_t shadow, direction_t direction)
Draw a separator line.
void draw_transfer(drawable_t *dest, drawable_t *src, const rect_t *destRect, const point_t *srcPoint)
Transfer pixels from one drawable to another.
void draw_text(drawable_t *draw, const rect_t *rect, const font_t *font, align_t xAlign, align_t yAlign, pixel_t pixel, const char *text)
Draw text to a drawable.
void draw_dashed_outline(drawable_t *draw, const rect_t *rect, pixel_t pixel, uint32_t length, int32_t width)
Draw a dashed outline just inside the given rectangle.
direction_t
Direction type.
void draw_bezel(drawable_t *draw, const rect_t *rect, uint64_t width, pixel_t pixel)
Draw a filled border bezel just inside the given rectangle.
void draw_invalidate(drawable_t *draw, const rect_t *rect)
Invalidate a rectangle in the drawable.
void draw_frame(drawable_t *draw, const rect_t *rect, uint64_t width, pixel_t foreground, pixel_t background)
Draw a skeuomorphic frame.
bool polygon_contains(double px, double py, const point_t *points, uint64_t pointCount)
Check if a point is inside a polygon.
#define CLAMP(x, low, high)
#define NULL
Pointer error value.
drawable_t * image_draw(image_t *image)
double atan2(double y, double x)
#define PIXEL_BLEND(dest, src)
#define PIXEL_GREEN(pixel)
#define PIXEL_BLUE(pixel)
#define PIXEL_ARGB(a, r, g, b)
#define PIXEL_ALPHA(pixel)
#define RECT_SHRINK(rect, margin)
#define RECT_FIT(rect, parent)
#define RECT_INIT_DIM(x, y, width, height)
#define RECT_HEIGHT(rect)
#define RECT_EXPAND_TO_CONTAIN(rect, other)
_PUBLIC void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *))
_PUBLIC void * memmove(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
_PUBLIC void * memset32(void *s, __UINT32_TYPE__ c, size_t n)
_PUBLIC void * memcpy(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
_PUBLIC size_t strlen(const char *s)
uint32_t glyphOffsets[256]