From b4b587563efc8376e257422cc25c4adf70cf91f0 Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: May 02 2021 10:21:09 +0000 Subject: enable/disable antialiasing --- diff --git a/demo/src/SConstruct b/demo/src/SConstruct index 3e03308..57421d1 100644 --- a/demo/src/SConstruct +++ b/demo/src/SConstruct @@ -14,7 +14,8 @@ flags = ' -O0 -g -lm -Wall -fmessage-length=0 -fdebug-prefix-map=src=demo/src ' # files sources = [ - 'common.c', + 'common.c', + 'benchmark.c', 'drawing.c', 'font.c', 'framebuffer.c', diff --git a/demo/src/benchmark.c b/demo/src/benchmark.c new file mode 100644 index 0000000..52a088b --- /dev/null +++ b/demo/src/benchmark.c @@ -0,0 +1,142 @@ + +#include + +#include + +#include "common.h" + + +static const double convexShape[][2] = { + { 0, 10 }, + { 0, 3 }, + { 8, 0 }, + { 10, 3 }, + { 10, 10 } }; + +static const double nonConvexShape[][2] = { + { 0, 0 }, + { 10, 0 }, + { 10, 3 }, + { 3, 3 }, + { 3, 5 }, + { 7, 5 }, + { 7, 7 }, + { 3, 7 }, + { 3, 10 }, + { 0, 10 } }; + + +static int enableConvex = TRUE; +static int enableFill = TRUE; +static int enableStroke = TRUE; +static int enableTexture = TRUE; +static int enableStrokeTex = TRUE; +static int enableAA = TRUE; + +static Animation anim; + + +static unsigned long long frameTimes[20]; +static int frameIndex; + + +static void drawRandom(const double *shape, int count) { + double h = windowGetHeight(); + double w = windowGetWidth(); + srand(0); + for(int i = 0; i < 1000; ++i) { + double size = 16 + randomFloat()*(h/2 - 16); + double x = randomFloat()*(w - size) + size/2; + double y = randomFloat()*(h - size) + size/2; + double a = randomFloat()*360; + + saveState(); + translate(x, y); + zoom(size/10); + rotate(a); + translate(-5, -5); + moveTo(shape[0], shape[1]); + for(int k = 2; k < count; k += 2) + lineTo(shape[k], shape[k+1]); + closePath(); + restoreState(); + } +} + + +static void drawGrid(const double *shape, int count) { + saveState(); + const double s = 16; + double angle = windowGetSeconds()*20; + zoom(64/s); + for(int i = 0; i < 8; ++i) { + for(int j = 0; j < 16; ++j) { + saveState(); + translate(s/2, s/2); + rotate(angle); + translate(3-s/2, 3-s/2); + moveTo(shape[0], shape[1]); + for(int k = 2; k < count; k += 2) + lineTo(shape[k], shape[k+1]); + closePath(); + restoreState(); + translate(s, 0); + } + translate(-16*s, s); + } + restoreState(); +} + + +void benchmarkInit() { + anim = createAnimationEx("data/sprite/bricks-tile.png", TRUE, TRUE, TRUE); +} + + +void benchmarkDraw() { + saveState(); + noFill(); + noStroke(); + disableAntialiasing(); + if (enableFill) fill(colorByRGBA(1, 1, 1, 1)); + if (enableStroke) stroke(colorByRGBA(0.5, 0.5, 0.5, 1)); + if (enableTexture) fillTexture(anim, 0, 0, 16, 16, FALSE); + if (enableStrokeTex) strokeTexture(anim, 0, 0, 16, 16, TRUE); + if (enableAA) enableAntialiasing(); + + const double *shape = enableConvex ? *convexShape : *nonConvexShape; + int count = enableConvex ? (int)(sizeof(convexShape)/sizeof(**convexShape)) + : (int)(sizeof(nonConvexShape)/sizeof(**nonConvexShape)); + + drawRandom(shape, count); + drawGrid(shape, count); + restoreState(); + + int frameCount = (int)(sizeof(frameTimes)/sizeof(*frameTimes)); + unsigned long long t = windowGetMonotonicMilliseconds(); + unsigned long long dt = t - frameTimes[frameIndex]; + frameTimes[frameIndex] = t; + frameIndex = (frameIndex + 1)%frameCount; + double fps = dt > 0 ? frameCount*1000.0/(double)dt : 0.0; + + saveState(); + textFontDefault(); + textSize(16); + textf(16, 16, "fps: %6.2f", fps); + text( 16, 48, + "c - convex\n" + "f - fill\n" + "s - stroke\n" + "t - texture\n" + "y - stroke texture\n" + "a - antialiasing" ); + restoreState(); + + if (keyWentDown("c")) enableConvex = !enableConvex; + if (keyWentDown("f")) enableFill = !enableFill; + if (keyWentDown("s")) enableStroke = !enableStroke; + if (keyWentDown("t")) enableTexture = !enableTexture; + if (keyWentDown("y")) enableStrokeTex = !enableStrokeTex; + if (keyWentDown("a")) enableAA = !enableAA; +} + diff --git a/demo/src/benchmark.h b/demo/src/benchmark.h new file mode 100644 index 0000000..9d18f7a --- /dev/null +++ b/demo/src/benchmark.h @@ -0,0 +1,10 @@ +#ifndef BENCHMARK_H +#define BENCHMARK_H + + +void benchmarkInit(); +void benchmarkDraw(); + + +#endif + diff --git a/demo/src/drawing.c b/demo/src/drawing.c index 6f3341b..544791f 100644 --- a/demo/src/drawing.c +++ b/demo/src/drawing.c @@ -40,7 +40,7 @@ void drawingDraw() { fill(colorByName("green")); stroke(colorByName("magenta")); - regularPolygon(x + 24, y + 24, 6, 48); + regularPolygon(x + 24, y + 24, 6, 48, windowGetSeconds()*10); x += 64; stroke(colorByName("brown")); diff --git a/demo/src/main.c b/demo/src/main.c index 8ce5282..ef174c1 100644 --- a/demo/src/main.c +++ b/demo/src/main.c @@ -7,6 +7,10 @@ #include "font.h" #include "drawing.h" #include "framebuffer.h" +#include "benchmark.h" + + +static int benchmark = FALSE; void init() { @@ -16,27 +20,35 @@ void init() { fontInit(); drawingInit(); framebufferInit(); + benchmarkInit(); } void draw() { - commonDraw(); - framebufferDraw(); - drawingDraw(); - phisicsDraw(); - spritesDraw(); - fontDraw(); - - drawSprites(); - saveState(); - stroke(colorByName("red")); - strokeWidth(20); - point(mouseX(), mouseY()); - restoreState(); + if (benchmark) { + benchmarkDraw(); + } else { + commonDraw(); + framebufferDraw(); + drawingDraw(); + phisicsDraw(); + spritesDraw(); + fontDraw(); + + drawSprites(); + saveState(); + stroke(colorByName("red")); + strokeWidth(20); + point(mouseX(), mouseY()); + restoreState(); + } - if (keyDown("p")) { + if (keyWentDown("p")) { viewportSave("screenshot.png"); messageBox("screenshot saved to file: screenshot.png"); } + + if (keyWentDown("b")) + benchmark = !benchmark; } int main() { diff --git a/doc/helianthus-doc-ru.odt b/doc/helianthus-doc-ru.odt index 9a4938e..99de8cd 100644 Binary files a/doc/helianthus-doc-ru.odt and b/doc/helianthus-doc-ru.odt differ diff --git a/src/drawing.c b/src/drawing.c index 679011d..64ba582 100644 --- a/src/drawing.c +++ b/src/drawing.c @@ -13,7 +13,6 @@ static HeliDrawingState statesStack[1024]; static int statesStackIndex = 0; - typedef struct _HeliStrokePoint { double x, y, dx, dy; } HeliStrokePoint; @@ -29,6 +28,22 @@ static void endPath(int close, int stroke, int fill, int fillSimple); static void closePathSimple() { endPath(TRUE, TRUE, FALSE, TRUE); } +static int isStrokeSolid(HeliDrawingState *state, double *outAABorder) { + if ( state->strokeColor[3] >= 1.0 - HELI_PRECISION + && state->strokeWidth > HELI_PRECISION + && (!state->strokeTexture.animation || !animationGetGLTexId(state->strokeTexture.animation)) ) + { + double aaBorder = heliGLGetAAResolution(); + if (outAABorder) *outAABorder = aaBorder; + if (aaBorder > HELI_PRECISION && aaBorder < state->strokeWidth) + return TRUE; + } else + if (outAABorder) { + *outAABorder = heliGLGetAAResolution(); + } + return FALSE; +} + void heliDrawingApplyTexture(double *color, HeliTextureState *state) { glColor4dv(color); @@ -37,35 +52,64 @@ void heliDrawingApplyTexture(double *color, HeliTextureState *state) { HeliPair *pair = heliUIntGet(&heliDrawingFramebuffersToFlush, texid); if (pair) framebufferFlush((Framebuffer)pair->value); - unsigned int mode = state->fixed ? GL_EYE_LINEAR : GL_OBJECT_LINEAR; - unsigned int param = state->fixed ? GL_EYE_PLANE : GL_OBJECT_PLANE; - - double kx = fabs(state->width) > HELI_PRECISION ? 1/state->width - : state->width < 0 ? -HELI_PRECISION : HELI_PRECISION; - double ky = fabs(state->height) > HELI_PRECISION ? 1/state->height - : state->height < 0 ? -HELI_PRECISION : HELI_PRECISION; - double x[4] = { kx, 0, 0, -state->x*kx }; - double y[4] = { 0, ky, 0, -state->y*ky }; - glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texid); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, mode); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, mode); - glTexGendv(GL_S, param, x); - glTexGendv(GL_T, param, y); + if (state->fixed) { + unsigned int mode; + glGetIntegerv(GL_MATRIX_MODE, (int*)&mode); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGendv(GL_S, GL_EYE_PLANE, state->genx); + glTexGendv(GL_T, GL_EYE_PLANE, state->geny); + glPopMatrix(); + glMatrixMode(mode); + } else { + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGendv(GL_S, GL_OBJECT_PLANE, state->genx); + glTexGendv(GL_T, GL_OBJECT_PLANE, state->geny); + } } } void heliDrawingResetTexture() { - glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); + glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); glColor4d(1, 1, 1, 1); } +static void initTextureState(HeliTextureState *s, Animation animation, double x, double y, double width, double height, int fixed) { + s->animation = animation; + + double kx = fabs(width) > HELI_PRECISION ? 1/width + : width < 0 ? -HELI_PRECISION : HELI_PRECISION; + double ky = fabs(height) > HELI_PRECISION ? 1/height + : height < 0 ? -HELI_PRECISION : HELI_PRECISION; + double genx[4] = {kx, 0, 0, -x*kx}; + double geny[4] = {0, ky, 0, -y*ky}; + + if (fixed) { + s->fixed = TRUE; + double m[4][4]; + glGetDoublev(GL_MODELVIEW_MATRIX, *m); + for(int i = 0; i < 4; ++i) { + s->genx[i] = genx[0]*m[0][i] + genx[1]*m[1][i] + genx[2]*m[2][i] + genx[3]*m[3][i]; + s->geny[i] = geny[0]*m[0][i] + geny[1]*m[1][i] + geny[2]*m[2][i] + geny[3]*m[3][i]; + } + } else { + s->fixed = FALSE; + memcpy(s->genx, genx, sizeof(genx)); + memcpy(s->geny, geny, sizeof(geny)); + } +} + void background(unsigned int colorCode) { double color[4]; @@ -77,15 +121,8 @@ void clear() void fill(unsigned int colorCode) { heliColorToDouble(colorCode, heliDrawingGetState()->fillColor); } -void fillTexture(Animation animation, double x, double y, double width, double height, int fixed) { - HeliTextureState *s = &heliDrawingGetState()->fillTexture; - s->animation = animation; - s->x = x; - s->y = y; - s->width = width; - s->height = height; - s->fixed = fixed != 0; -} +void fillTexture(Animation animation, double x, double y, double width, double height, int fixed) + { initTextureState(&heliDrawingGetState()->fillTexture, animation, x, y, width, height, fixed); } void noFillColor() { fill(0); } void noFillTexture() @@ -95,15 +132,8 @@ void noFill() void stroke(unsigned int colorCode) { heliColorToDouble(colorCode, heliDrawingGetState()->strokeColor); } -void strokeTexture(Animation animation, double x, double y, double width, double height, int fixed) { - HeliTextureState *s = &heliDrawingGetState()->strokeTexture; - s->animation = animation; - s->x = x; - s->y = y; - s->width = width; - s->height = height; - s->fixed = fixed != 0; -} +void strokeTexture(Animation animation, double x, double y, double width, double height, int fixed) + { initTextureState(&heliDrawingGetState()->strokeTexture, animation, x, y, width, height, fixed); } void noStrokeColor() { stroke(0); } void noStrokeTexture() @@ -114,6 +144,11 @@ void noStroke() void strokeWidth(double width) { heliDrawingGetState()->strokeWidth = width; } +void enableAntialiasing() + { heliDrawingGetState()->antialiasing = TRUE; } +void disableAntialiasing() + { heliDrawingGetState()->antialiasing = FALSE; } + const char* rgba(double r, double g, double b, double a) { static char buf[1024]; snprintf(buf, sizeof(buf) - 1, "%f %f %f %f", r, g, b, a); @@ -212,7 +247,10 @@ void noTarget() void rect(double x, double y, double width, double height) { resetPath(); - heliFillRectSimple(x, y, x+width, y+height, heliGLGetAAResolution()); + HeliDrawingState *s = heliDrawingGetState(); + double aaBorder = 0; + int antialiasing = s->antialiasing && !isStrokeSolid(s, &aaBorder); + heliFillRectSimple(x, y, x+width, y+height, aaBorder, antialiasing); moveTo(x, y); lineTo(x + width, y); lineTo(x + width, y + height); @@ -237,7 +275,10 @@ void line(double x1, double y1, double x2, double y2) { void ellipse(double x, double y, double width, double height) { resetPath(); if (fabs(fabs(width) - fabs(height)) <= HELI_PRECISION) { - heliFillCircleSimple(x + 0.5*width, y + 0.5*height, 0.5*width, heliGLGetAAResolution()); + HeliDrawingState *s = heliDrawingGetState(); + double aaBorder = 0; + int antialiasing = s->antialiasing && !isStrokeSolid(s, &aaBorder); + heliFillCircleSimple(x + 0.5*width, y + 0.5*height, 0.5*width, aaBorder, antialiasing); arcPath(x, y, width, height, 0, 360); endPath(TRUE, TRUE, FALSE, FALSE); } else { @@ -292,13 +333,13 @@ void arc(double x, double y, double w, double h, double start, double stop) { strokePath(); } -void regularPolygon(double x, double y, int sides, double size) { +void regularPolygon(double x, double y, int sides, double radius, double angle) { + angle *= PI/180.0; resetPath(); - size *= 0.5; - moveTo(x + size, y); + moveTo(x + radius*cos(angle), y + radius*sin(angle)); for(int i = 1; i < sides; ++i) { - double a = i*2*PI/sides; - lineTo(x + size*cos(a), y + size*sin(a)); + double a = i*2*PI/sides + angle; + lineTo(x + radius*cos(a), y + radius*sin(a)); } closePathSimple(); } @@ -308,19 +349,20 @@ void resetPath() { pathSize = 0; } -void heliFillCircleSimple(double x, double y, double r, double aaBorder) { +void heliFillCircleSimple(double x, double y, double r, double aaBorder, int antialiasing) { r = fabs(r); if (r < HELI_PRECISION) return; HeliDrawingState *s = heliDrawingGetState(); if (s->fillColor[3] <= HELI_PRECISION) return; + if (!s->antialiasing) antialiasing = FALSE; heliDrawingApplyTexture(s->fillColor, &s->fillTexture); double step = 1/r; if (step > PI/180) step = PI/180; - if (aaBorder < HELI_PRECISION) { - glEnable(GL_MULTISAMPLE); + if (!antialiasing || aaBorder < HELI_PRECISION) { + if (antialiasing) glEnable(GL_MULTISAMPLE); glBegin(GL_TRIANGLE_FAN); for(double a = 0; a < 2*PI; a += step) glVertex2d(x + cos(a)*r, y + sin(a)*r); glEnd(); @@ -351,15 +393,16 @@ void heliFillCircleSimple(double x, double y, double r, double aaBorder) { } -void heliFillRectSimple(double x0, double y0, double x1, double y1, double aaBorder) { +void heliFillRectSimple(double x0, double y0, double x1, double y1, double aaBorder, int antialiasing) { if (fabs(x1 - x0) < HELI_PRECISION || fabs(y1 - y0) < HELI_PRECISION) return; HeliDrawingState *s = heliDrawingGetState(); if (s->fillColor[3] <= HELI_PRECISION) return; + if (!s->antialiasing) antialiasing = FALSE; heliDrawingApplyTexture(s->fillColor, &s->fillTexture); - if (aaBorder <= HELI_PRECISION) { - glEnable(GL_MULTISAMPLE); + if (!antialiasing || aaBorder <= HELI_PRECISION) { + if (antialiasing) glEnable(GL_MULTISAMPLE); glBegin(GL_QUADS); glVertex2d(x0, y0); glVertex2d(x1, y0); @@ -426,13 +469,13 @@ void heliFillRectSimple(double x0, double y0, double x1, double y1, double aaBor } -static void drawFillSimple() { +static void drawFillSimple(int antialiasing) { HeliDrawingState *s = heliDrawingGetState(); if (s->fillColor[3] <= HELI_PRECISION) return; if (pathSize < 6) return; heliDrawingApplyTexture(s->fillColor, &s->fillTexture); - glEnable(GL_MULTISAMPLE); + if (antialiasing && s->antialiasing) glEnable(GL_MULTISAMPLE); glBegin(GL_TRIANGLE_FAN); for(int i = 0; i < pathSize; i += 2) glVertex2dv(&path[i]); @@ -441,7 +484,7 @@ static void drawFillSimple() { heliDrawingResetTexture(); } -static void drawFill() { +static void drawFill(int antialiasing) { HeliDrawingState *s = heliDrawingGetState(); if (s->fillColor[3] <= HELI_PRECISION) return; if (pathSize < 6) return; @@ -459,7 +502,7 @@ static void drawFill() { l -= 1; r += 1; t -= 1; b += 1; - glEnable(GL_MULTISAMPLE); + if (antialiasing && s->antialiasing) glEnable(GL_MULTISAMPLE); glEnable(GL_STENCIL_TEST); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); @@ -597,9 +640,9 @@ static void strokeAddCorner( } } -static void strokeDraw(HeliStroke *stroke, double w, double *color) { +static void strokeDraw(HeliStroke *stroke, double w, double *color, int antialiasing) { const double aaBorder = heliGLGetAAResolution(); - if (aaBorder > HELI_PRECISION) { + if (antialiasing && aaBorder > HELI_PRECISION) { double c0[4] = { color[0], color[1], color[2], 0 }; double c1[4] = { color[0], color[1], color[2], color[3] }; double w0 = w + 0.5*aaBorder; @@ -633,7 +676,7 @@ static void strokeDraw(HeliStroke *stroke, double w, double *color) { glColor4d(1, 1, 1, 1); } else { glColor4dv(color); - glEnable(GL_MULTISAMPLE); + if (antialiasing) glEnable(GL_MULTISAMPLE); glBegin(GL_TRIANGLE_STRIP); for(int i = 0; i < stroke->count; ++i) { HeliStrokePoint *p = stroke->points + i; @@ -658,8 +701,9 @@ static void drawStroke(int close) { stroke.points = calloc(stroke.allocatedCount, sizeof(*stroke.points)); double w = 0.5*s->strokeWidth; - double ps = heliGLGetPixelSize(); + double ps = heliGLGetPixelSize(); double precisionSqr = ps > HELI_PRECISION ? ps : 0.5*w; + precisionSqr *= 0.5; precisionSqr *= precisionSqr; heliDrawingApplyTexture(s->strokeColor, &s->strokeTexture); @@ -681,7 +725,7 @@ static void drawStroke(int close) { stroke.points[0].y, stroke.points[0].dx, stroke.points[0].dy ); - strokeDraw(&stroke, w, s->strokeColor); + strokeDraw(&stroke, w, s->strokeColor, s->antialiasing); stroke.count = 0; @@ -701,7 +745,7 @@ static void drawStroke(int close) { stroke.points[0].y, stroke.points[0].dx, stroke.points[0].dy ); - strokeDraw(&stroke, w, s->strokeColor); + strokeDraw(&stroke, w, s->strokeColor, s->antialiasing); } else { double px = 0, py = 0, nx = 0, ny = 0; for(int i = 0; i < pathSize; i += 2) { @@ -722,7 +766,7 @@ static void drawStroke(int close) { strokeAddCorner(&stroke, px, py, x, y, nx, ny, precisionSqr); } memcpy(stroke.points + stroke.count - 1, stroke.points, sizeof(*stroke.points)); - strokeDraw(&stroke, w, s->strokeColor); + strokeDraw(&stroke, w, s->strokeColor, s->antialiasing); } heliDrawingResetTexture(); @@ -764,12 +808,45 @@ static void endPath(int close, int stroke, int fill, int fillSimple) { && fabs(path[pathSize-1] - path[1]) <= 2*HELI_PRECISION ) pathSize -= 2; + // if shape convex? + if (pathSize >= 6 && fill && !fillSimple) { + int convex = TRUE; + int d = 0; + double x0 = path[pathSize-4]; + double y0 = path[pathSize-3]; + double x1 = path[pathSize-2]; + double y1 = path[pathSize-1]; + for(int i = 0; i < pathSize; i += 2) { + double x2 = path[i]; + double y2 = path[i+1]; + double xx0 = x1 - x0; + double yy0 = y1 - y0; + double xx1 = y1 - y2; + double yy1 = x2 - x1; + double dot = xx0*xx1 + yy0*yy1; + double ll2 = (xx0*xx0 + yy0*yy0)*(xx1*xx1 + yy1*yy1); + double s2 = dot*dot/ll2; + if (s2 > HELI_PRECISION_SQR) { + int dd = dot > 0.0 ? 1 : -1; + if (!d) d = dd; else + if (d != dd) { convex = FALSE; break; } + x0 = x1; y0 = y1; + x1 = x2; y1 = y2; + } + } + if (convex) { fill = FALSE; fillSimple = TRUE; } + } + // draw int isPoint = FALSE; double px, py; if (pathSize >= 4) { - if (fillSimple) drawFillSimple(); - else if (fill) drawFill(); + if (pathSize >= 6 && (fillSimple || fill)) { + HeliDrawingState *s = heliDrawingGetState(); + int antialiasing = s->antialiasing && (!stroke || !isStrokeSolid(s, NULL)); + if (fillSimple) drawFillSimple(antialiasing); + else drawFill(antialiasing); + } if (stroke) drawStroke(close); } else if (origPathSize >= 4 && stroke) { @@ -816,6 +893,7 @@ void resetStateEx(unsigned int flags) { if (flags & STATE_BACKGROUND ) background(COLOR_WHITE); if (flags & STATE_TRANSFORM ) noTransform(); if (flags & STATE_CLIP ) noClip(); + if (flags & STATE_ANTIALIASING ) enableAntialiasing(); } void saveState() @@ -861,6 +939,8 @@ void restoreState() { curr->fontSize = prev->fontSize; if (flags & STATE_TEXT_FONT) curr->font = prev->font; + if (flags & STATE_ANTIALIASING) + curr->antialiasing = prev->antialiasing; } void heliDrawingClearFrame() { diff --git a/src/drawing.h b/src/drawing.h index 49a9058..d2d00da 100644 --- a/src/drawing.h +++ b/src/drawing.h @@ -26,6 +26,7 @@ typedef enum _StateFlags { STATE_BACKGROUND = 1 << 11, STATE_TRANSFORM = 1 << 12, STATE_CLIP = 1 << 13, + STATE_ANTIALIASING = 1 << 14, STATE_FILL = STATE_FILL_COLOR | STATE_FILL_TEXTURE, @@ -46,7 +47,8 @@ typedef enum _StateFlags { | STATE_BACKGROUND | STATE_TRANSFORM | STATE_CLIP - | STATE_TARGET, + | STATE_TARGET + | STATE_ANTIALIASING, } StateFlags; @@ -56,11 +58,18 @@ void clear(); void fill(unsigned int colorCode); void fillTexture(Animation animation, double x, double y, double width, double height, int fixed); void noFill(); +void noFillColor(); +void noFillTexture(); void stroke(unsigned int colorCode); void strokeTexture(Animation animation, double x, double y, double width, double height, int fixed); void noStroke(); +void noStrokeColor(); +void noStrokeTexture(); void strokeWidth(double width); +void enableAntialiasing(); +void disableAntialiasing(); + void translate(double x, double y); void rotate(double angle); void zoom(double z); @@ -117,7 +126,7 @@ void arc(double x, double y, double w, double h, double start, double stop); void arcPath(double x, double y, double w, double h, double start, double stop); void line(double x1, double y1, double x2, double y2); void point(double x, double y); -void regularPolygon(double x, double y, int sides, double size); +void regularPolygon(double x, double y, int sides, double radius, double angle); void moveTo(double x, double y); void lineTo(double x, double y); diff --git a/src/font.c b/src/font.c index 8d360c2..23913a9 100644 --- a/src/font.c +++ b/src/font.c @@ -648,7 +648,8 @@ void textLayoutDrawSubstr(TextLayout layout, double x, double y, int start, int const double texBorder = 0.5*FONT_MAP_BORDERSIZE/FONT_MAP_TEXSIZE; const double texGlyphSize = (double)FONT_MAP_GLYPHWORKSIZE/FONT_MAP_TEXSIZE; - if (!heliGLIsIntegerClipping()) glEnable(GL_MULTISAMPLE); + if (drawingState->antialiasing && !heliGLIsIntegerClipping()) + glEnable(GL_MULTISAMPLE); glPushMatrix(); glTranslated(x, y, 0); glScaled(fontScale, fontScale, 1); diff --git a/src/gl.c b/src/gl.c index 821f2e9..aea90d3 100644 --- a/src/gl.c +++ b/src/gl.c @@ -90,7 +90,7 @@ double heliGLGetPixelSize() { if (l0 > l1) { double l = l0; l0 = l1; l1 = l; } if (l0 <= HELI_PRECISION && l1 <= HELI_PRECISION) return 0; - double l = sqrt(l0*l1); + double l = sqrt(l0*l1); return l <= HELI_PRECISION ? 0 : l; } diff --git a/src/private.h b/src/private.h index 1c08c1b..4d818c6 100644 --- a/src/private.h +++ b/src/private.h @@ -187,14 +187,14 @@ void heliObjectUnregister(void *o); // drawing typedef struct _HeliTextureState { - double color[4]; Animation animation; int fixed; - double x, y, width, height; + double genx[4], geny[4]; } HeliTextureState; typedef struct _HeliDrawingState { unsigned int flags; + int antialiasing; double fillColor[4]; double strokeColor[4]; double strokeWidth; @@ -213,8 +213,8 @@ HeliDrawingState *heliDrawingGetState(); HeliDrawingState *heliDrawingGetStateStack(); void heliDrawingApplyTexture(double *color, HeliTextureState *state); void heliDrawingResetTexture(); -void heliFillRectSimple(double x0, double y0, double x1, double y1, double aaBorder); -void heliFillCircleSimple(double x, double y, double r, double aaBorder); +void heliFillRectSimple(double x0, double y0, double x1, double y1, double aaBorder, int antialiasing); +void heliFillCircleSimple(double x, double y, double r, double aaBorder, int antialiasing); void heliDrawingClearFrame(); void heliDrawingPrepareFrame(); void heliDrawingFinish();