void Canvas::DrawCircle(int x, int y, unsigned radius) { SDLRasterCanvas canvas(buffer); if (!brush.IsHollow()) { const auto color = canvas.Import(brush.GetColor()); if (brush.GetColor().IsOpaque()) canvas.FillCircle(x, y, radius, color); else canvas.FillCircle(x, y, radius, color, AlphaPixelOperations<ActivePixelTraits>(brush.GetColor().Alpha())); } if (IsPenOverBrush()) { if (pen.GetWidth() < 2) { canvas.DrawCircle(x, y, radius, canvas.Import(pen.GetColor())); return; } // no thickCircleColor in SDL_gfx, so need to emulate it with multiple draws (slow!) for (int i= (pen.GetWidth()/2); i>= -(int)(pen.GetWidth()-1)/2; --i) { canvas.DrawCircle(x, y, radius + i, canvas.Import(pen.GetColor())); } } }
void Rectangle(PixelScalar left, PixelScalar top, PixelScalar right, PixelScalar bottom) { DrawFilledRectangle(left, top, right, bottom, brush); if (IsPenOverBrush()) DrawOutlineRectangle(left, top, right, bottom); }
void Canvas::DrawPolygon(const RasterPoint *lppt, unsigned cPoints) { if (brush.IsHollow() && !pen.IsDefined()) return; SDLRasterCanvas canvas(buffer); static_assert(sizeof(RasterPoint) == sizeof(SDLRasterCanvas::Point), "Incompatible point types"); const SDLRasterCanvas::Point *points = reinterpret_cast<const SDLRasterCanvas::Point *>(lppt); if (!brush.IsHollow()) { const auto color = canvas.Import(brush.GetColor()); if (brush.GetColor().IsOpaque()) canvas.FillPolygon(points, cPoints, color); else canvas.FillPolygon(points, cPoints, color, AlphaPixelOperations<ActivePixelTraits>(brush.GetColor().Alpha())); } if (IsPenOverBrush()) ::DrawPolyline(canvas, ActivePixelTraits(), pen, lppt, cPoints, true); }
void Canvas::DrawTriangleFan(const RasterPoint *points, unsigned num_points) { if (brush.IsHollow() && !pen.IsDefined()) return; #ifdef USE_GLSL OpenGL::solid_shader->Use(); #endif ScopeVertexPointer vp(points); if (!brush.IsHollow() && num_points >= 3) { brush.Set(); glDrawArrays(GL_TRIANGLE_FAN, 0, num_points); } if (IsPenOverBrush()) { pen.Bind(); if (pen.GetWidth() <= 2) { glDrawArrays(GL_LINE_LOOP, 0, num_points); } else { unsigned vertices = LineToTriangles(points, num_points, vertex_buffer, pen.GetWidth(), true); if (vertices > 0) { vp.Update(vertex_buffer.begin()); glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices); } } pen.Unbind(); } }
void Canvas::DrawTriangleFan(const RasterPoint *points, unsigned num_points) { if (brush.IsHollow() && !pen.IsDefined()) return; glVertexPointer(2, GL_VALUE, 0, points); if (!brush.IsHollow() && num_points >= 3) { brush.Set(); glDrawArrays(GL_TRIANGLE_FAN, 0, num_points); } if (IsPenOverBrush()) { pen.Bind(); if (pen.GetWidth() <= 2) { glDrawArrays(GL_LINE_LOOP, 0, num_points); } else { unsigned vertices = LineToTriangles(points, num_points, vertex_buffer, pen.GetWidth(), true); if (vertices > 0) { glVertexPointer(2, GL_VALUE, 0, vertex_buffer.begin()); glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices); } } pen.Unbind(); } }
void Canvas::DrawPolygon(const RasterPoint *points, unsigned num_points) { if (brush.IsHollow() && !pen.IsDefined()) return; #ifdef USE_GLSL OpenGL::solid_shader->Use(); #endif ScopeVertexPointer vp(points); if (!brush.IsHollow() && num_points >= 3) { brush.Bind(); std::unique_ptr<const GLBlend> blend; if(!brush.IsOpaque()) { blend = std::make_unique<const GLBlend>(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } static AllocatedArray<GLushort> triangle_buffer; unsigned idx_count = PolygonToTriangles(points, num_points, triangle_buffer); if (idx_count > 0) glDrawElements(GL_TRIANGLES, idx_count, GL_UNSIGNED_SHORT, triangle_buffer.begin()); } if (IsPenOverBrush()) { pen.Bind(); if (pen.GetWidth() <= 2) { glDrawArrays(GL_LINE_LOOP, 0, num_points); } else { unsigned vertices = LineToTriangles(points, num_points, vertex_buffer, pen.GetWidth(), true); if (vertices > 0) { vp.Update(vertex_buffer.begin()); glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices); } } pen.Unbind(); } }
void Canvas::DrawPolygon(const BulkPixelPoint *lppt, unsigned cPoints) { if (brush.IsHollow() && !pen.IsDefined()) return; SDLRasterCanvas canvas(buffer); if (!brush.IsHollow()) { const auto color = canvas.Import(brush.GetColor()); if (brush.GetColor().IsOpaque()) canvas.FillPolygon(lppt, cPoints, color); else canvas.FillPolygon(lppt, cPoints, color, AlphaPixelOperations<ActivePixelTraits>(brush.GetColor().Alpha())); } if (IsPenOverBrush()) ::DrawPolyline(canvas, ActivePixelTraits(), pen, lppt, cPoints, true); }
void Canvas::DrawPolygon(const RasterPoint *points, unsigned num_points) { if (brush.IsHollow() && !pen.IsDefined()) return; glVertexPointer(2, GL_VALUE, 0, points); if (!brush.IsHollow() && num_points >= 3) { brush.Set(); static AllocatedArray<GLushort> triangle_buffer; unsigned idx_count = PolygonToTriangles(points, num_points, triangle_buffer); if (idx_count > 0) glDrawElements(GL_TRIANGLES, idx_count, GL_UNSIGNED_SHORT, triangle_buffer.begin()); } if (IsPenOverBrush()) { pen.Bind(); if (pen.GetWidth() <= 2) { glDrawArrays(GL_LINE_LOOP, 0, num_points); } else { unsigned vertices = LineToTriangles(points, num_points, vertex_buffer, pen.GetWidth(), true); if (vertices > 0) { glVertexPointer(2, GL_VALUE, 0, vertex_buffer.begin()); glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices); } } pen.Unbind(); } }
void Rectangle(int left, int top, int right, int bottom) { DrawFilledRectangle(left, top, right, bottom, brush); if (IsPenOverBrush()) DrawOutlineRectangle(left, top, right, bottom, pen); }
void Canvas::DrawAnnulus(int x, int y, unsigned small_radius, unsigned big_radius, Angle start, Angle end) { if (1 == 1) { /* TODO: switched to the unoptimised generic implementation due to TRAC #2221, caused by rounding error of start/end radial; should reimplement GLDonutVertices to use the exact start/end radial */ ::Annulus(*this, x, y, big_radius, start, end, small_radius); return; } ScopeVertexPointer vp; GLDonutVertices vertices(x, y, small_radius, big_radius); const std::pair<unsigned,unsigned> i = AngleToDonutVertices(start, end); const unsigned istart = i.first; const unsigned iend = i.second; if (!brush.IsHollow()) { brush.Set(); vertices.Bind(vp); if (istart > iend) { glDrawArrays(GL_TRIANGLE_STRIP, istart, GLDonutVertices::MAX_ANGLE - istart + 2); glDrawArrays(GL_TRIANGLE_STRIP, 0, iend + 2); } else { glDrawArrays(GL_TRIANGLE_STRIP, istart, iend - istart + 2); } } if (IsPenOverBrush()) { pen.Bind(); if (istart != iend && iend != GLDonutVertices::MAX_ANGLE) { if (brush.IsHollow()) vertices.Bind(vp); glDrawArrays(GL_LINE_STRIP, istart, 2); glDrawArrays(GL_LINE_STRIP, iend, 2); } const unsigned pstart = istart / 2; const unsigned pend = iend / 2; vertices.BindInnerCircle(vp); if (pstart < pend) { glDrawArrays(GL_LINE_STRIP, pstart, pend - pstart + 1); } else { glDrawArrays(GL_LINE_STRIP, pstart, GLDonutVertices::CIRCLE_SIZE - pstart + 1); glDrawArrays(GL_LINE_STRIP, 0, pend + 1); } vertices.BindOuterCircle(vp); if (pstart < pend) { glDrawArrays(GL_LINE_STRIP, pstart, pend - pstart + 1); } else { glDrawArrays(GL_LINE_STRIP, pstart, GLDonutVertices::CIRCLE_SIZE - pstart + 1); glDrawArrays(GL_LINE_STRIP, 0, pend + 1); } pen.Unbind(); } }
void Canvas::DrawCircle(int x, int y, unsigned radius) { #ifdef USE_GLSL OpenGL::solid_shader->Use(); #endif if (IsPenOverBrush() && pen.GetWidth() > 2) { ScopeVertexPointer vp; GLDonutVertices vertices(x, y, radius - pen.GetWidth() / 2, radius + pen.GetWidth() / 2); if (!brush.IsHollow()) { vertices.BindInnerCircle(vp); brush.Set(); glDrawArrays(GL_TRIANGLE_FAN, 0, vertices.CIRCLE_SIZE); } vertices.Bind(vp); pen.Bind(); glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.SIZE); pen.Unbind(); } else { GLFallbackArrayBuffer &buffer = radius < 16 ? *OpenGL::small_circle_buffer : *OpenGL::circle_buffer; const unsigned n = radius < 16 ? OpenGL::SMALL_CIRCLE_SIZE : OpenGL::CIRCLE_SIZE; const FloatPoint *const points = (const FloatPoint *)buffer.BeginRead(); const ScopeVertexPointer vp(points); #ifdef USE_GLSL glm::mat4 matrix2 = glm::scale(glm::translate(glm::mat4(), glm::vec3(x, y, 0)), glm::vec3(GLfloat(radius), GLfloat(radius), 1.)); glUniformMatrix4fv(OpenGL::solid_modelview, 1, GL_FALSE, glm::value_ptr(matrix2)); #else glPushMatrix(); #ifdef HAVE_GLES glTranslatex((GLfixed)x << 16, (GLfixed)y << 16, 0); glScalex((GLfixed)radius << 16, (GLfixed)radius << 16, (GLfixed)1 << 16); #else glTranslatef(x, y, 0.); glScalef(radius, radius, 1.); #endif #endif if (!brush.IsHollow()) { brush.Set(); glDrawArrays(GL_TRIANGLE_FAN, 0, n); } if (IsPenOverBrush()) { pen.Bind(); glDrawArrays(GL_LINE_LOOP, 0, n); pen.Unbind(); } #ifdef USE_GLSL glUniformMatrix4fv(OpenGL::solid_modelview, 1, GL_FALSE, glm::value_ptr(glm::mat4())); #else glPopMatrix(); #endif buffer.EndRead(); } }
void Canvas::DrawCircle(int x, int y, unsigned radius) { if (IsPenOverBrush() && pen.GetWidth() > 2) { GLDonutVertices vertices(x, y, radius - pen.GetWidth() / 2, radius + pen.GetWidth() / 2); if (!brush.IsHollow()) { vertices.bind_inner_circle(); brush.Set(); glDrawArrays(GL_TRIANGLE_FAN, 0, vertices.CIRCLE_SIZE); } vertices.bind(); pen.Set(); glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.SIZE); } else if (OpenGL::vertex_buffer_object && radius < 16) { /* draw a "small" circle with VBO */ OpenGL::small_circle_buffer->Bind(); glVertexPointer(2, GL_SHORT, 0, NULL); glPushMatrix(); #ifdef HAVE_GLES glTranslatex((GLfixed)x << 16, (GLfixed)y << 16, 0); glScalex((GLfixed)radius << 8, (GLfixed)radius << 8, (GLfixed)1 << 16); #else glTranslatef(x, y, 0.); glScalef(radius / 256., radius / 256., 1.); #endif if (!brush.IsHollow()) { brush.Set(); glDrawArrays(GL_TRIANGLE_FAN, 0, OpenGL::SMALL_CIRCLE_SIZE); } if (IsPenOverBrush()) { pen.Bind(); glDrawArrays(GL_LINE_LOOP, 0, OpenGL::SMALL_CIRCLE_SIZE); pen.Unbind(); } glPopMatrix(); OpenGL::small_circle_buffer->Unbind(); } else if (OpenGL::vertex_buffer_object) { /* draw a "big" circle with VBO */ OpenGL::circle_buffer->Bind(); glVertexPointer(2, GL_SHORT, 0, NULL); glPushMatrix(); #ifdef HAVE_GLES glTranslatex((GLfixed)x << 16, (GLfixed)y << 16, 0); glScalex((GLfixed)radius << 6, (GLfixed)radius << 6, (GLfixed)1 << 16); #else glTranslatef(x, y, 0.); glScalef(radius / 1024., radius / 1024., 1.); #endif if (!brush.IsHollow()) { brush.Set(); glDrawArrays(GL_TRIANGLE_FAN, 0, OpenGL::CIRCLE_SIZE); } if (IsPenOverBrush()) { pen.Bind(); glDrawArrays(GL_LINE_LOOP, 0, OpenGL::CIRCLE_SIZE); pen.Unbind(); } glPopMatrix(); OpenGL::circle_buffer->Unbind(); } else { GLCircleVertices vertices(x, y, radius); vertices.bind(); if (!brush.IsHollow()) { brush.Set(); glDrawArrays(GL_TRIANGLE_FAN, 0, vertices.SIZE); } if (IsPenOverBrush()) { pen.Bind(); glDrawArrays(GL_LINE_LOOP, 0, vertices.SIZE); pen.Unbind(); } } }