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)
 
 
  594    if (draw == 
NULL || 
string == 
NULL || point == 
NULL || length == 0)
 
  609    for (
uint64_t i = 0; i < length; i++)
 
 
  639        aligned->
x = rect->
left;
 
  648        aligned->
x = rect->
left;
 
  655        aligned->
y = rect->
top;
 
  658        aligned->
y = rect->
top + (
RECT_HEIGHT(rect) / 2) - (visualTextHeight / 2);
 
  664        aligned->
y = rect->
top;
 
 
  672    if (draw == 
NULL || rect == 
NULL || text == 
NULL || *text == 
'\0')
 
  686    if (textWidth <= maxWidth)
 
  690        draw_string(draw, font, &startPoint, pixel, text, originalTextLen);
 
  694        const char* ellipsis = 
"...";
 
  697        const char* drawText = text;
 
  699        const char* drawEllipsis = 
NULL;
 
  701        if (ellipsisWidth <= maxWidth)
 
  706            for (
uint64_t i = 0; i < originalTextLen; ++i)
 
  709                if (i < originalTextLen - 1)
 
  714                if (currentContentWidth + charWidth + ellipsisWidth <= maxWidth)
 
  716                    currentContentWidth += charWidth;
 
  726            drawTextLen = fittedOriginalLen;
 
  727            drawEllipsis = ellipsis;
 
  742                if (currentContentWidth + charWidth <= maxWidth)
 
  744                    currentContentWidth += charWidth;
 
  754            drawTextLen = fittedEllipsisLen;
 
  759        if (drawEllipsis != 
NULL)
 
  765            totalWidth = 
font_width(font, drawText, drawTextLen);
 
  774            startPoint.
x = rect->
left;
 
  783            startPoint.
x = rect->
left;
 
  790            startPoint.
y = rect->
top;
 
  793            startPoint.
y = rect->
top + (
RECT_HEIGHT(rect) / 2) - (visualTextHeight / 2);
 
  799            startPoint.
y = rect->
top;
 
  803        draw_string(draw, font, &startPoint, pixel, drawText, drawTextLen);
 
  805        if (drawEllipsis != 
NULL)
 
  809            draw_string(draw, font, &ellipsisStartPoint, pixel, drawEllipsis, 3);
 
 
  815    pixel_t pixel, 
const char* text)
 
  817    if (draw == 
NULL || rect == 
NULL || text == 
NULL || *text == 
'\0')
 
  834    const char* textPtr = text;
 
  836    while (*textPtr != 
'\0')
 
  838        const char* lineStart = textPtr;
 
  839        const char* lineEnd = textPtr;
 
  840        const char* lastSpace = 
NULL;
 
  843        while (*textPtr != 
'\0' && *textPtr != 
'\n')
 
  855                if (*(textPtr + 1) != 
'\0' && *(textPtr + 1) != 
'\n')
 
  860                if (currentWidth > maxWidth && lastSpace != 
NULL)
 
  870        if (*textPtr == 
'\n' || *textPtr == 
'\0')
 
  874        else if (lastSpace == 
NULL)
 
  881        if (*textPtr == 
'\n')
 
  885        else if (*textPtr != 
'\0')
 
  887            textPtr = lineEnd + 1;
 
  891    int32_t totalTextHeight = lineCount * lineHeight;
 
  897        startY = fitRect.
top;
 
  900        startY = fitRect.
top + (
RECT_HEIGHT(&fitRect) / 2) - (totalTextHeight / 2);
 
  906        startY = fitRect.
top;
 
  913    while (*textPtr != 
'\0' && currentY + lineHeight <= fitRect.
bottom)
 
  915        const char* lineStart = textPtr;
 
  916        const char* lineEnd = textPtr;
 
  917        const char* lastSpace = 
NULL;
 
  920        while (*textPtr != 
'\0' && *textPtr != 
'\n')
 
  932                if (*(textPtr + 1) != 
'\0' && *(textPtr + 1) != 
'\n')
 
  937                if (currentWidth > maxWidth && lastSpace != 
NULL)
 
  947        if (*textPtr == 
'\n' || *textPtr == 
'\0')
 
  951        else if (lastSpace == 
NULL)
 
  956        int64_t lineLength = lineEnd - lineStart;
 
  963            lineX = fitRect.
left;
 
  972            lineX = fitRect.
left;
 
  976        point_t linePos = {.
x = lineX, .y = currentY};
 
  977        draw_string(draw, font, &linePos, pixel, lineStart, lineLength);
 
  979        currentY += lineHeight;
 
  981        if (*textPtr == 
'\n')
 
  985        else if (*textPtr != 
'\0')
 
  987            textPtr = lineEnd + 1;
 
 
  996    if (draw == 
NULL || rect == 
NULL || width == 0)
 
 1001    draw_frame(draw, rect, width / 2, background, foreground);
 
 1003    rect_t innerRect = *rect;
 
 1005    draw_frame(draw, &innerRect, width / 2, foreground, background);
 
 
 1026            .right = fitRect.
left + width / 2,
 
 1027            .bottom = fitRect.
bottom};
 
 1030            .right = fitRect.
right,
 
 1031            .bottom = fitRect.
bottom};
 
 1043            .right = fitRect.
right,
 
 1044            .bottom = fitRect.
top + height / 2};
 
 1046            .top = fitRect.
top + height / 2,
 
 1047            .right = fitRect.
right,
 
 1048            .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]