37#include "ocpn_plugin.h"
40#include "ocpn_frame.h"
50#include <wx/graphics.h>
51#include <wx/dcclient.h>
56#include "wx28compat.h"
60#include "glChartCanvas.h"
64extern float g_GLMinSymbolLineWidth;
65wxArrayPtrVoid gTesselatorVertices;
67#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
68extern GLint color_tri_shader_program;
69extern GLint circle_filled_shader_program;
70extern GLint texture_2D_shader_program;
77#define PI 3.1415926535897931160E0
82 : m_glchartCanvas(&canvas), m_glcanvas(NULL), dc(NULL), m_pen(wxNullPen), m_brush(wxNullBrush) {
83#if wxUSE_GRAPHICS_CONTEXT
87 m_textforegroundcolour = wxColour(0, 0, 0);
89 m_buseTex = GetLocaleCanonicalName().IsSameAs(_T(
"en_US"));
92 s_odc_tess_work_buf = NULL;
93 m_canvasIndex = m_glchartCanvas->GetCanvasIndex();
96#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
97 s_odc_tess_vertex_idx = 0;
98 s_odc_tess_vertex_idx_this = 0;
99 s_odc_tess_buf_len = 0;
101 s_odc_tess_work_buf = (GLfloat *)malloc(100 *
sizeof(GLfloat));
102 s_odc_tess_buf_len = 100;
107ocpnDC::ocpnDC(wxGLCanvas &canvas)
108 : m_glchartCanvas(NULL), m_glcanvas(&canvas), dc(NULL), m_pen(wxNullPen), m_brush(wxNullBrush) {
109#if wxUSE_GRAPHICS_CONTEXT
113 m_textforegroundcolour = wxColour(0, 0, 0);
115 m_buseTex = GetLocaleCanonicalName().IsSameAs(_T(
"en_US"));
118 s_odc_tess_work_buf = NULL;
122#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
123 s_odc_tess_vertex_idx = 0;
124 s_odc_tess_vertex_idx_this = 0;
125 s_odc_tess_buf_len = 0;
127 s_odc_tess_work_buf = (GLfloat *)malloc(100 *
sizeof(GLfloat));
128 s_odc_tess_buf_len = 100;
133ocpnDC::ocpnDC(wxDC &pdc)
134 : m_glchartCanvas(NULL), m_glcanvas(NULL), dc(&pdc), m_pen(wxNullPen), m_brush(wxNullBrush) {
135#if wxUSE_GRAPHICS_CONTEXT
137 wxMemoryDC *pmdc = wxDynamicCast(dc, wxMemoryDC);
139 pgc = wxGraphicsContext::Create(*pmdc);
141 wxClientDC *pcdc = wxDynamicCast(dc, wxClientDC);
142 if (pcdc) pgc = wxGraphicsContext::Create(*pcdc);
145 m_textforegroundcolour = wxColour(0, 0, 0);
146 m_buseTex = GetLocaleCanonicalName().IsSameAs(_T(
"en_US"));
149 s_odc_tess_work_buf = NULL;
156 : m_glchartCanvas(NULL), m_glcanvas(NULL), dc(NULL), m_pen(wxNullPen), m_brush(wxNullBrush) {
157#if wxUSE_GRAPHICS_CONTEXT
160 m_buseTex = GetLocaleCanonicalName().IsSameAs(_T(
"en_US"));
163 s_odc_tess_work_buf = NULL;
169#if wxUSE_GRAPHICS_CONTEXT
174 free(s_odc_tess_work_buf);
177 m_glchartCanvas = canvas;
178 m_canvasIndex = m_glchartCanvas->GetCanvasIndex();
181void ocpnDC::Clear() {
186 wxBrush tmpBrush = m_brush;
188 if (m_glchartCanvas) {
189 SetBrush(wxBrush(m_glchartCanvas->GetBackgroundColour()));
190 m_glchartCanvas->GetSize(&w, &h);
192 else if (m_glcanvas) {
193 SetBrush(wxBrush(m_glcanvas->GetBackgroundColour()));
194 m_glcanvas->GetSize(&w, &h);
199 DrawRectangle(0, 0, w, h);
205void ocpnDC::SetBackground(
const wxBrush &brush) {
207 dc->SetBackground(brush);
211 m_glchartCanvas->SetBackgroundColour(brush.GetColour());
213 m_glcanvas->SetBackgroundColour(brush.GetColour());
220void ocpnDC::SetPen(
const wxPen &pen) {
222 if (pen == wxNullPen)
223 dc->SetPen(*wxTRANSPARENT_PEN);
230void ocpnDC::SetBrush(
const wxBrush &brush) {
237void ocpnDC::SetTextForeground(
const wxColour &colour) {
239 dc->SetTextForeground(colour);
241 m_textforegroundcolour = colour;
244void ocpnDC::SetFont(
const wxFont &font) {
251const wxPen &ocpnDC::GetPen()
const {
252 if (dc)
return dc->GetPen();
256const wxBrush &ocpnDC::GetBrush()
const {
257 if (dc)
return dc->GetBrush();
261const wxFont &ocpnDC::GetFont()
const {
262 if (dc)
return dc->GetFont();
266void ocpnDC::GetSize(wxCoord *width, wxCoord *height)
const {
268 dc->GetSize(width, height);
271 if (m_glchartCanvas){
272 *width = m_glchartCanvas->GetGLCanvasWidth();
273 *height = m_glchartCanvas->GetGLCanvasHeight();
275 else if (m_glcanvas){
276 m_glcanvas->GetSize(width, height);
282void ocpnDC::SetGLAttrs(
bool highQuality) {
287 if (g_GLOptions.m_GLLineSmoothing) glEnable(GL_LINE_SMOOTH);
288 if (g_GLOptions.m_GLPolygonSmoothing) glEnable(GL_POLYGON_SMOOTH);
289 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
292 glDisable(GL_LINE_SMOOTH);
293 glDisable(GL_POLYGON_SMOOTH);
299void ocpnDC::SetGLStipple()
const {
302#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
303 switch (m_pen.GetStyle()) {
304 case wxPENSTYLE_DOT: {
305 glLineStipple(1, 0x3333);
306 glEnable(GL_LINE_STIPPLE);
309 case wxPENSTYLE_LONG_DASH: {
310 glLineStipple(1, 0xFFF8);
311 glEnable(GL_LINE_STIPPLE);
314 case wxPENSTYLE_SHORT_DASH: {
315 glLineStipple(1, 0x3F3F);
316 glEnable(GL_LINE_STIPPLE);
319 case wxPENSTYLE_DOT_DASH: {
320 glLineStipple(1, 0x8FF1);
321 glEnable(GL_LINE_STIPPLE);
333void DrawEndCap(
float x1,
float y1,
float t1,
float angle) {
334#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
335 const int steps = 16;
338 for (
int i = 0; i <= steps; i++) {
339 float a = angle + M_PI / 2 + M_PI / steps * i;
341 float xb = x1 + t1 / 2 * cos(a);
342 float yb = y1 + t1 / 2 * sin(a);
357void ocpnDC::DrawGLThickLine(
float x1,
float y1,
float x2,
float y2, wxPen pen,
361 float angle = atan2f(y2 - y1, x2 - x1);
362 float t1 = pen.GetWidth();
363 float t2sina1 = t1 / 2 * sinf(angle);
364 float t2cosa1 = t1 / 2 * cosf(angle);
370 wxColor c = pen.GetColour();
372 colorv[0] = c.Red() / float(256);
373 colorv[1] = c.Green() / float(256);
374 colorv[2] = c.Blue() / float(256);
375 colorv[3] = c.Alpha() / float(256);
376 shader->SetUniform4fv(
"color", colorv);
382 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
383 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)I);
396 shader->SetAttributePointerf(
"position", vert);
402 int n_dashes = pen.GetDashes(&dashes);
404 float lpix = sqrtf(powf((
float)(x1 - x2), 2) + powf((
float)(y1 - y2), 2));
408 float ldraw = t1 * dashes[0];
409 float lspace = t1 * dashes[1];
443 glUseProgram(color_tri_shader_program);
447 glBindBuffer(GL_ARRAY_BUFFER, 0);
448 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
450 GLint pos = glGetAttribLocation(color_tri_shader_program,
"position");
451 glEnableVertexAttribArray(pos);
452 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float), vert);
459 glGetUniformLocation(color_tri_shader_program,
"TransformMatrix");
460 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)I);
462 matloc = glGetUniformLocation(color_tri_shader_program,
"MVMatrix");
465 (
const GLfloat *)gFrame->GetPrimaryCanvas()->GetpVP()->vp_transform);
467 wxColor c = pen.GetColour();
469 colorv[0] = c.Red() / float(256);
470 colorv[1] = c.Green() / float(256);
471 colorv[2] = c.Blue() / float(256);
472 colorv[3] = c.Alpha() / float(256);
474 GLint colloc = glGetUniformLocation(color_tri_shader_program,
"color");
475 glUniform4fv(colloc, 1, colorv);
478 while (lrun < lpix) {
480 float xb = xa + ldraw * cosf(angle);
481 float yb = ya + ldraw * sinf(angle);
483 if ((lrun + ldraw) >= lpix)
489 vert[0] = xa + t2sina1;
490 vert[1] = ya - t2cosa1;
491 vert[2] = xb + t2sina1;
492 vert[3] = yb - t2cosa1;
493 vert[4] = xb - t2sina1;
494 vert[5] = yb + t2cosa1;
495 vert[6] = xb - t2sina1;
496 vert[7] = yb + t2cosa1;
497 vert[8] = xa - t2sina1;
498 vert[9] = ya + t2cosa1;
499 vert[10] = xa + t2sina1;
500 vert[11] = ya - t2cosa1;
502 glDrawArrays(GL_TRIANGLES, 0, 6);
509 xb = xa + lspace * cos(angle);
510 yb = ya + lspace * sin(angle);
518 vert[0] = x1 + t2sina1;
519 vert[1] = y1 - t2cosa1;
520 vert[2] = x2 + t2sina1;
521 vert[3] = y2 - t2cosa1;
522 vert[4] = x2 - t2sina1;
523 vert[5] = y2 + t2cosa1;
524 vert[6] = x2 - t2sina1;
525 vert[7] = y2 + t2cosa1;
526 vert[8] = x1 - t2sina1;
527 vert[9] = y1 + t2cosa1;
528 vert[10] = x1 + t2sina1;
529 vert[11] = y1 - t2cosa1;
532 glUseProgram(color_tri_shader_program);
535 glBindBuffer(GL_ARRAY_BUFFER, 0);
536 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
538 GLint pos = glGetAttribLocation(color_tri_shader_program,
"position");
539 glEnableVertexAttribArray(pos);
540 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float), vert);
547 glGetUniformLocation(color_tri_shader_program,
"TransformMatrix");
548 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)I);
550 matloc = glGetUniformLocation(color_tri_shader_program,
"MVMatrix");
553 (
const GLfloat *)gFrame->GetPrimaryCanvas()->GetpVP()->vp_transform);
555 wxColor c = pen.GetColour();
557 colorv[0] = c.Red() / float(256);
558 colorv[1] = c.Green() / float(256);
559 colorv[2] = c.Blue() / float(256);
560 colorv[3] = c.Alpha() / float(256);
562 GLint colloc = glGetUniformLocation(color_tri_shader_program,
"color");
563 glUniform4fv(colloc, 1, colorv);
566 glDrawArrays(GL_TRIANGLES, 0, 6);
583void ocpnDC::DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2,
585 if (dc) dc->DrawLine(x1, y1, x2, y2);
587 else if (ConfigurePen()) {
588 bool b_draw_thick =
false;
590 float pen_width = wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth());
598 if (g_GLOptions.m_GLLineSmoothing) glEnable(GL_LINE_SMOOTH);
601 if (pen_width > 1.0) {
603 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
604 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
605 if (pen_width > parms[1])
608 glLineWidth(pen_width);
610 glLineWidth(pen_width);
614 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
615 if (pen_width > parms[1])
618 glLineWidth(pen_width);
620 glLineWidth(pen_width);
623#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
625 DrawGLThickLine(x1, y1, x2, y2, m_pen, b_hiqual);
632 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
633 shader->SetUniform1f(
"uLineWidth", pen_width);
634 shader->SetUniform1f(
"uBlendFactor", 1.5);
639 GetSize(&width, &height);
643 shader->SetUniform2fv(
"uViewPort", vpx);
646 colorv[0] = m_pen.GetColour().Red() / float(256);
647 colorv[1] = m_pen.GetColour().Green() / float(256);
648 colorv[2] = m_pen.GetColour().Blue() / float(256);
651 shader->SetUniform4fv(
"color", colorv);
654 shader->SetAttributePointerf(
"position", fBuf);
658 int n_dashes = m_pen.GetDashes(&dashes);
660 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
661 float cosa = cosf(angle);
662 float sina = sinf(angle);
663 float t1 = m_pen.GetWidth();
665 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
669 float ldraw = t1 * dashes[0];
670 float lspace = t1 * dashes[1];
672 ldraw = wxMax(ldraw, 4.0);
673 lspace = wxMax(lspace, 4.0);
674 lpix = wxMin(lpix, 2000.0);
676 while (lrun < lpix) {
678 float xb = xa + ldraw * cosa;
679 float yb = ya + ldraw * sina;
681 if ((lrun + ldraw) >= lpix)
692 glDrawArrays(GL_LINES, 0, 2);
694 xa = xa + (lspace + ldraw) * cosa;
695 ya = ya + (lspace + ldraw) * sina;
696 lrun += lspace + ldraw;
705 glDrawArrays(GL_LINES, 0, 2);
712 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
719 GetSize(&width, &height);
726 colorv[0] = m_pen.GetColour().Red() / float(256);
727 colorv[1] = m_pen.GetColour().Green() / float(256);
728 colorv[2] = m_pen.GetColour().Blue() / float(256);
731 shader->SetUniform4fv(
"color", colorv);
733 glLineWidth(wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth()));
736 shader->SetAttributePointerf(
"position", fBuf);
740 int n_dashes = m_pen.GetDashes(&dashes);
742 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
743 float cosa = cosf(angle);
744 float sina = sinf(angle);
745 float t1 = m_pen.GetWidth();
747 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
751 float ldraw = t1 * dashes[0];
752 float lspace = t1 * dashes[1];
754 ldraw = wxMax(ldraw, 4.0);
755 lspace = wxMax(lspace, 4.0);
756 lpix = wxMin(lpix, 2000.0);
758 while (lrun < lpix) {
760 float xb = xa + ldraw * cosa;
761 float yb = ya + ldraw * sina;
763 if ((lrun + ldraw) >= lpix)
774 glDrawArrays(GL_LINES, 0, 2);
776 xa = xa + (lspace + ldraw) * cosa;
777 ya = ya + (lspace + ldraw) * sina;
778 lrun += lspace + ldraw;
787 glDrawArrays(GL_LINES, 0, 2);
797 glDisable(GL_LINE_STIPPLE);
800 glDisable(GL_LINE_SMOOTH);
809void ocpnDC::DrawGLThickLines(
int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,
810 wxPen pen,
bool b_hiqual) {
814 wxPoint p0 = points[0];
815 for (
int i = 1; i < n; i++) {
816 DrawGLThickLine(p0.x + xoffset, p0.y + yoffset, points[i].x + xoffset,
817 points[i].y + yoffset, pen, b_hiqual);
824void ocpnDC::DrawLines(
int n, wxPoint points[], wxCoord xoffset,
825 wxCoord yoffset,
bool b_hiqual) {
826 if (dc) dc->DrawLines(n, points, xoffset, yoffset);
828 else if (ConfigurePen()) {
833 SetGLAttrs(b_hiqual);
835 bool b_draw_thick =
false;
837 glDisable(GL_LINE_STIPPLE);
843 if (m_pen.GetWidth() > 1) {
845 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
846 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
848 if (m_pen.GetWidth() > parms[1])
851 glLineWidth(wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth()));
853 glLineWidth(wxMax(g_GLMinSymbolLineWidth, 1));
855 if (m_pen.GetWidth() > 1) {
857 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
858 if (m_pen.GetWidth() > parms[1])
861 glLineWidth(wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth()));
863 glLineWidth(wxMax(g_GLMinSymbolLineWidth, 1));
867 DrawGLThickLines(n, points, xoffset, yoffset, m_pen, b_hiqual);
870 glDisable(GL_LINE_STIPPLE);
871 glDisable(GL_LINE_SMOOTH);
872 glDisable(GL_POLYGON_SMOOTH);
880 if (workBufSize < (
size_t)n * 2) {
881 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
885 for (
int i = 0; i < n; i++) {
886 workBuf[i * 2] = points[i].x + xoffset;
887 workBuf[(i * 2) + 1] = points[i].y + yoffset;
894 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
895 shader->SetUniform1f(
"uLineWidth", m_pen.GetWidth());
896 shader->SetUniform1f(
"uBlendFactor", 2.0);
901 GetSize(&width, &height);
905 shader->SetUniform2fv(
"uViewPort", vpx);
908 colorv[0] = m_pen.GetColour().Red() / float(256);
909 colorv[1] = m_pen.GetColour().Green() / float(256);
910 colorv[2] = m_pen.GetColour().Blue() / float(256);
913 shader->SetUniform4fv(
"color", colorv);
915 shader->SetAttributePointerf(
"position", workBuf);
917 glDrawArrays(GL_LINE_STRIP, 0, n);
924 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
927 colorv[0] = m_pen.GetColour().Red() / float(256);
928 colorv[1] = m_pen.GetColour().Green() / float(256);
929 colorv[2] = m_pen.GetColour().Blue() / float(256);
932 shader->SetUniform4fv(
"color", colorv);
934 shader->SetAttributePointerf(
"position", workBuf);
936 glDrawArrays(GL_LINE_STRIP, 0, n);
944 glDisable(GL_LINE_STIPPLE);
945 glDisable(GL_LINE_SMOOTH);
946 glDisable(GL_POLYGON_SMOOTH);
953void ocpnDC::StrokeLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) {
954#if wxUSE_GRAPHICS_CONTEXT
956 pgc->SetPen(dc->GetPen());
957 pgc->StrokeLine(x1, y1, x2, y2);
959 dc->CalcBoundingBox(x1, y1);
960 dc->CalcBoundingBox(x2, y2);
963 DrawLine(x1, y1, x2, y2,
true);
966void ocpnDC::StrokeLines(
int n, wxPoint *points) {
970#if wxUSE_GRAPHICS_CONTEXT
972 wxPoint2DDouble *dPoints =
973 (wxPoint2DDouble *)malloc(n *
sizeof(wxPoint2DDouble));
974 for (
int i = 0; i < n; i++) {
975 dPoints[i].m_x = points[i].x;
976 dPoints[i].m_y = points[i].y;
978 pgc->SetPen(dc->GetPen());
979 pgc->StrokeLines(n, dPoints);
983 DrawLines(n, points, 0, 0,
true);
986void ocpnDC::DrawRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h) {
987 if (dc) dc->DrawRectangle(x, y, w, h);
990 DrawRoundedRectangle(x, y, w, h, 0);
996static void drawrrhelper(wxCoord x0, wxCoord y0, wxCoord r,
int quadrant,
999#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1000 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
1004 x = r, y = 0, dx = 0, dy = -rs, ddx = -rss, ddy = rss;
1007 x = 0, y = -r, dx = -rs, dy = 0, ddx = rss, ddy = rss;
1010 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
1013 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
1019 for (
int i = 0; i < steps; i++) {
1020 glVertex2i(x0 + floor(x), y0 + floor(y));
1021 x += dx + ddx / 2, y += dy + ddy / 2;
1022 dx += ddx, dy += ddy;
1024 glVertex2i(x0 + floor(x), y0 + floor(y));
1029void ocpnDC::drawrrhelperGLES2(wxCoord x0, wxCoord y0, wxCoord r,
int quadrant,
1032 if (steps == 0)
return;
1034 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
1038 x = r, y = 0, dx = 0, dy = -rs, ddx = -rss, ddy = rss;
1041 x = 0, y = -r, dx = -rs, dy = 0, ddx = rss, ddy = rss;
1044 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
1047 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
1053 for (
int i = 0; i < steps; i++) {
1054 workBuf[workBufIndex++] = x0 + floor(x);
1055 workBuf[workBufIndex++] = y0 + floor(y);
1057 x += dx + ddx / 2, y += dy + ddy / 2;
1058 dx += ddx, dy += ddy;
1061 workBuf[workBufIndex++] = x0 + floor(x);
1062 workBuf[workBufIndex++] = y0 + floor(y);
1066void ocpnDC::DrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
1068 if (dc) dc->DrawRoundedRectangle(x, y, w, h, r);
1072 int steps = ceil(sqrt((
float)r));
1074 wxCoord x1 = x + r, x2 = x + w - r;
1075 wxCoord y1 = y + r, y2 = y + h - r;
1081 size_t bufReq = steps * 8 * 2 *
sizeof(float);
1083 if (workBufSize < bufReq) {
1084 workBuf = (
float *)realloc(workBuf, bufReq);
1085 workBufSize = bufReq;
1090 drawrrhelperGLES2(x2, y1, r, 0, steps);
1091 drawrrhelperGLES2(x1, y1, r, 1, steps);
1092 drawrrhelperGLES2(x1, y2, r, 2, steps);
1093 drawrrhelperGLES2(x2, y2, r, 3, steps);
1100 fcolorv[0] = m_brush.GetColour().Red() / float(256);
1101 fcolorv[1] = m_brush.GetColour().Green() / float(256);
1102 fcolorv[2] = m_brush.GetColour().Blue() / float(256);
1103 fcolorv[3] = m_brush.GetColour().Alpha() / float(256);
1104 shader->SetUniform4fv(
"color", fcolorv);
1113 mat4x4_rotate_Z(Q, I, angle);
1121 X, (
float(*)[4])m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform, Q);
1122 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)X);
1125 shader->SetAttributePointerf(
"position", workBuf);
1128 glDrawArrays(GL_TRIANGLE_FAN, 0, workBufIndex / 2);
1132 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1133 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1134 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1135 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1137 shader->SetUniform4fv(
"color", bcolorv);
1140 glDrawArrays(GL_LINE_LOOP, 0, workBufIndex / 2);
1147void ocpnDC::DrawCircle(wxCoord x, wxCoord y, wxCoord radius) {
1151 coords[0] = x - radius;
1152 coords[1] = y + radius;
1153 coords[2] = x + radius;
1154 coords[3] = y + radius;
1155 coords[4] = x - radius;
1156 coords[5] = y - radius;
1157 coords[6] = x + radius;
1158 coords[7] = y - radius;
1160 GLShaderProgram *shader = pcircle_filled_shader_program[m_canvasIndex];
1163 shader->SetUniform1f(
"circle_radius", radius);
1169 GetSize(&width, &height);
1170 ctrv[1] = height - y;
1171 shader->SetUniform2fv(
"circle_center", ctrv);
1175 colorv[0] = m_brush.GetColour().Red() / float(256);
1176 colorv[1] = m_brush.GetColour().Green() / float(256);
1177 colorv[2] = m_brush.GetColour().Blue() / float(256);
1178 colorv[3] = (m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT) ? 0.0 : 1.0;
1180 shader->SetUniform4fv(
"circle_color", colorv);
1184 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1185 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1186 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1187 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1189 shader->SetUniform4fv(
"border_color", bcolorv);
1192 shader->SetUniform1f(
"border_width", m_pen.GetWidth());
1194 shader->SetAttributePointerf(
"aPos", coords);
1197 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1202void ocpnDC::StrokeCircle(wxCoord x, wxCoord y, wxCoord radius) {
1203#if wxUSE_GRAPHICS_CONTEXT
1205 wxGraphicsPath gpath = pgc->CreatePath();
1206 gpath.AddCircle(x, y, radius);
1208 pgc->SetPen(GetPen());
1209 pgc->SetBrush(GetBrush());
1210 pgc->DrawPath(gpath);
1213 dc->CalcBoundingBox(x + radius + 2, y + radius + 2);
1214 dc->CalcBoundingBox(x - radius - 2, y - radius - 2);
1217 DrawCircle(x, y, radius);
1220void ocpnDC::DrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height) {
1221 if (dc) dc->DrawEllipse(x, y, width, height);
1224 float r1 = width / 2, r2 = height / 2;
1225 float cx = x + r1, cy = y + r2;
1231 float steps = floorf(
1232 wxMax(sqrtf(sqrtf((
float)(width * width + height * height))), 1) *
1236 glDisable(GL_BLEND);
1241void ocpnDC::DrawPolygon(
int n, wxPoint points[], wxCoord xoffset,
1242 wxCoord yoffset,
float scale,
float angle) {
1243 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1258 shader->SetUniform1f(
"uLineWidth", m_pen.GetWidth());
1259 shader->SetUniform1f(
"uBlendFactor", 2.0);
1264 GetSize(&width, &height);
1268 shader->SetUniform2fv(
"uViewPort", vpx);
1271 colorv[0] = m_pen.GetColour().Red() / float(256);
1272 colorv[1] = m_pen.GetColour().Green() / float(256);
1273 colorv[2] = m_pen.GetColour().Blue() / float(256);
1276 shader->SetUniform4fv(
"color", colorv);
1283 mat4x4_rotate_Z(Q, I, angle);
1291 X, (
float(*)[4])m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform,
1294 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)X);
1299 if (ConfigureBrush())
1300 DrawPolygonTessellated(n, points, xoffset, yoffset);
1304 if (workBufSize < (
size_t)n * 2) {
1305 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
1306 workBufSize = n * 4;
1309 for (
int i = 0; i < n; i++) {
1310 workBuf[i * 2] = (points[i].x *
scale);
1311 workBuf[i * 2 + 1] = (points[i].y *
scale);
1317 shader->SetAttributePointerf(
"position", workBuf);
1320 glDrawArrays(GL_LINE_LOOP, 0, n);
1324 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
1331 if (workBufSize < (
size_t)n * 2) {
1332 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
1333 workBufSize = n * 4;
1336 for (
int i = 0; i < n; i++) {
1337 workBuf[i * 2] = (points[i].x *
scale);
1338 workBuf[i * 2 + 1] = (points[i].y *
scale);
1348 bcolorv[0] = m_brush.GetColour().Red() / float(256);
1349 bcolorv[1] = m_brush.GetColour().Green() / float(256);
1350 bcolorv[2] = m_brush.GetColour().Blue() / float(256);
1351 bcolorv[3] = m_brush.GetColour().Alpha() / float(256);
1352 shader->SetUniform4fv(
"color", bcolorv);
1357 mat4x4_rotate_Z(Q, I, angle);
1365 X, (
float(*)[4])m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform,
1367 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)X);
1369 shader->SetAttributePointerf(
"position", workBuf);
1374 float x1 = workBuf[4];
1375 float y1 = workBuf[5];
1376 workBuf[4] = workBuf[6];
1377 workBuf[5] = workBuf[7];
1381 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1382 }
else if (n == 3) {
1383 glDrawArrays(GL_TRIANGLES, 0, 3);
1387 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
1393 for (
int i = 0; i < n; i++) {
1394 workBuf[i * 2] = (points[i].x *
scale);
1395 workBuf[i * 2 + 1] = (points[i].y *
scale);
1398 shader = pAALine_shader_program[m_canvasIndex];
1401 shader->SetAttributePointerf(
"position", workBuf);
1403 glDrawArrays(GL_LINE_LOOP, 0, n);
1407 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
1435#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
1437static std::list<double *> odc_combine_work_data;
1438static void odc_combineCallbackD(GLdouble coords[3], GLdouble *vertex_data[4],
1439 GLfloat weight[4], GLdouble **dataOut,
1447void odc_vertexCallbackD_GLSL(GLvoid *vertex,
void *data) {
1451 if (pDC->s_odc_tess_vertex_idx > pDC->s_odc_tess_buf_len - 8) {
1452 int new_buf_len = pDC->s_odc_tess_buf_len + 100;
1453 GLfloat *tmp = pDC->s_odc_tess_work_buf;
1455 pDC->s_odc_tess_work_buf = (GLfloat *)realloc(
1456 pDC->s_odc_tess_work_buf, new_buf_len *
sizeof(GLfloat));
1457 if (NULL == pDC->s_odc_tess_work_buf) {
1461 pDC->s_odc_tess_buf_len = new_buf_len;
1464 GLdouble *pointer = (GLdouble *)vertex;
1466 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[0];
1467 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[1];
1469 pDC->s_odc_nvertex++;
1472void odc_beginCallbackD_GLSL(GLenum mode,
void *data) {
1474 pDC->s_odc_tess_vertex_idx_this = pDC->s_odc_tess_vertex_idx;
1475 pDC->s_odc_tess_mode = mode;
1476 pDC->s_odc_nvertex = 0;
1479void odc_endCallbackD_GLSL(
void *data) {
1483 GLShaderProgram *shader = pcolor_tri_shader_program[pDC->m_canvasIndex];
1487 wxColour c = pDC->GetBrush().GetColour();
1489 colorv[0] = c.Red() / float(256);
1490 colorv[1] = c.Green() / float(256);
1491 colorv[2] = c.Blue() / float(256);
1492 colorv[3] = c.Alpha() / float(256);
1493 shader->SetUniform4fv(
"color", colorv);
1495 float *bufPt = &(pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx_this]);
1496 shader->SetAttributePointerf(
"position", bufPt);
1498 glDrawArrays(pDC->s_odc_tess_mode, 0, pDC->s_odc_nvertex);
1503 glUseProgram(color_tri_shader_program);
1506 glBindBuffer(GL_ARRAY_BUFFER, 0);
1507 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1509 float *bufPt = &(pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx_this]);
1510 GLint pos = glGetAttribLocation(color_tri_shader_program,
"position");
1511 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float), bufPt);
1512 glEnableVertexAttribArray(pos);
1519 wxColour c = pDC->GetBrush().GetColour();
1521 colorv[0] = c.Red() / float(256);
1522 colorv[1] = c.Green() / float(256);
1523 colorv[2] = c.Blue() / float(256);
1524 colorv[3] = c.Alpha() / float(256);
1526 GLint colloc = glGetUniformLocation(color_tri_shader_program,
"color");
1527 glUniform4fv(colloc, 1, colorv);
1529 glDrawArrays(pDC->s_odc_tess_mode, 0, pDC->s_odc_nvertex);
1539void ocpnDC::DrawPolygonTessellated(
int n, wxPoint points[], wxCoord xoffset,
1541 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1544#if !defined(ocpnUSE_GLES) || \
1545 defined(USE_ANDROID_GLES2)
1549 DrawPolygon(n, points, xoffset, yoffset);
1553#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
1554 m_tobj = gluNewTess();
1555 s_odc_tess_vertex_idx = 0;
1557 gluTessCallback(m_tobj, GLU_TESS_VERTEX_DATA,
1558 (_GLUfuncptr)&odc_vertexCallbackD_GLSL);
1559 gluTessCallback(m_tobj, GLU_TESS_BEGIN_DATA,
1560 (_GLUfuncptr)&odc_beginCallbackD_GLSL);
1561 gluTessCallback(m_tobj, GLU_TESS_END_DATA,
1562 (_GLUfuncptr)&odc_endCallbackD_GLSL);
1563 gluTessCallback(m_tobj, GLU_TESS_COMBINE_DATA,
1564 (_GLUfuncptr)&odc_combineCallbackD);
1567 gluTessNormal(m_tobj, 0, 0, 1);
1568 gluTessProperty(m_tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
1570 if (ConfigureBrush()) {
1571 gluTessBeginPolygon(m_tobj,
this);
1572 gluTessBeginContour(m_tobj);
1574 ViewPort *pvp = m_glchartCanvas->m_pParentCanvas->GetpVP();
1576 for (
int i = 0; i < n; i++) {
1577 double *p =
new double[6];
1579 if (fabs(pvp->rotation) > 0.01) {
1580 float cx = pvp->pix_width / 2.;
1581 float cy = pvp->pix_height / 2.;
1582 float c = cosf(pvp->rotation);
1583 float s = sinf(pvp->rotation);
1584 float xn = points[i].x - cx;
1585 float yn = points[i].y - cy;
1586 p[0] = xn * c - yn * s + cx;
1587 p[1] = xn * s + yn * c + cy;
1590 p[0] = points[i].x, p[1] = points[i].y, p[2] = 0;
1592 gluTessVertex(m_tobj, p, p);
1594 gluTessEndContour(m_tobj);
1595 gluTessEndPolygon(m_tobj);
1598 gluDeleteTess(m_tobj);
1608 static GLUtesselator *tobj = NULL;
1609 if (!tobj) tobj = gluNewTess();
1611 gluTessCallback(tobj, GLU_TESS_VERTEX, (_GLUfuncptr)&ocpnDCvertexCallback);
1612 gluTessCallback(tobj, GLU_TESS_BEGIN, (_GLUfuncptr)&ocpnDCbeginCallback);
1613 gluTessCallback(tobj, GLU_TESS_END, (_GLUfuncptr)&ocpnDCendCallback);
1614 gluTessCallback(tobj, GLU_TESS_COMBINE,
1615 (_GLUfuncptr)&ocpnDCcombineCallback);
1616 gluTessCallback(tobj, GLU_TESS_ERROR, (_GLUfuncptr)&ocpnDCerrorCallback);
1618 gluTessNormal(tobj, 0, 0, 1);
1619 gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
1621 if (ConfigureBrush()) {
1622 gluTessBeginPolygon(tobj, NULL);
1623 gluTessBeginContour(tobj);
1625 for (
int i = 0; i < n; i++) {
1626 GLvertex *vertex =
new GLvertex();
1627 gTesselatorVertices.Add(vertex);
1628 vertex->info.x = (GLdouble)points[i].x;
1629 vertex->info.y = (GLdouble)points[i].y;
1630 vertex->info.z = (GLdouble)0.0;
1631 vertex->info.r = (GLdouble)0.0;
1632 vertex->info.g = (GLdouble)0.0;
1633 vertex->info.b = (GLdouble)0.0;
1634 gluTessVertex(tobj, (GLdouble *)vertex, (GLdouble *)vertex);
1636 gluTessEndContour(tobj);
1637 gluTessEndPolygon(tobj);
1640 for (
unsigned int i = 0; i < gTesselatorVertices.Count(); i++)
1641 delete (GLvertex *)gTesselatorVertices[i];
1642 gTesselatorVertices.Clear();
1644 gluDeleteTess(tobj);
1653void ocpnDC::StrokePolygon(
int n, wxPoint points[], wxCoord xoffset,
1654 wxCoord yoffset,
float scale) {
1655#if wxUSE_GRAPHICS_CONTEXT
1657 wxGraphicsPath gpath = pgc->CreatePath();
1658 gpath.MoveToPoint(points[0].x *
scale + xoffset,
1659 points[0].y *
scale + yoffset);
1660 for (
int i = 1; i < n; i++)
1661 gpath.AddLineToPoint(points[i].x *
scale + xoffset,
1662 points[i].y *
scale + yoffset);
1663 gpath.AddLineToPoint(points[0].x *
scale + xoffset,
1664 points[0].y *
scale + yoffset);
1666 pgc->SetPen(GetPen());
1667 pgc->SetBrush(GetBrush());
1668 pgc->DrawPath(gpath);
1670 for (
int i = 0; i < n; i++)
1671 dc->CalcBoundingBox(points[i].x *
scale + xoffset,
1672 points[i].y *
scale + yoffset);
1675 DrawPolygon(n, points, xoffset, yoffset,
scale);
1678void ocpnDC::DrawBitmap(
const wxBitmap &bitmap, wxCoord x, wxCoord y,
1681 if (x < 0 || y < 0) {
1682 int dx = (x < 0 ? -x : 0);
1683 int dy = (y < 0 ? -y : 0);
1684 int w = bitmap.GetWidth() - dx;
1685 int h = bitmap.GetHeight() - dy;
1687 if (w <= 0 || h <= 0)
return;
1688 wxBitmap newBitmap = bitmap.GetSubBitmap(wxRect(dx, dy, w, h));
1695 if (dc) dc->DrawBitmap(bmp, x, y, usemask);
1703#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1704 wxImage image = bmp.ConvertToImage();
1705 int w = image.GetWidth(), h = image.GetHeight();
1708 unsigned char *d = image.GetData();
1709 unsigned char *a = image.GetAlpha();
1712 if (image.HasMask()) a = 0;
1714 unsigned char mr, mg, mb;
1715 if (!a && !image.GetOrFindMaskColour(&mr, &mg, &mb)) {
1716 printf(
"trying to use mask to draw a bitmap without alpha or mask\n");
1719 unsigned char *e =
new unsigned char[4 * w * h];
1721 for (
int y = 0; y < h; y++)
1722 for (
int x = 0; x < w; x++) {
1723 unsigned char r, g, b;
1724 int off = (y * w + x);
1734 a ? a[off] : ((r == mr) && (g == mg) && (b == mb) ? 0 : 255);
1740 glColor4f(1, 1, 1, 1);
1741 GLDrawBlendData(x, y, w, h, GL_RGBA, e);
1744 glRasterPos2i(x, y);
1746 if (image.GetData())
1747 glDrawPixels(w, h, GL_RGB, GL_UNSIGNED_BYTE, image.GetData());
1755void ocpnDC::DrawText(
const wxString &text, wxCoord x, wxCoord y,
float angle) {
1756 if (dc) dc->DrawText(text, x, y);
1764 m_texfont.Build(m_font, 1.0, m_dpi_factor);
1765 m_texfont.GetTextExtent(text, &w, &h);
1766 m_texfont.SetColor(m_textforegroundcolour);
1770 glEnable(GL_TEXTURE_2D);
1771 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1773 m_texfont.RenderString(text, x, y, angle);
1775 glDisable(GL_TEXTURE_2D);
1776 glDisable(GL_BLEND);
1780 sdc.SetFont(m_font);
1781 sdc.GetTextExtent(text, &w, &h, NULL, NULL, &m_font);
1786 temp_dc.SelectObject(bmp);
1789 temp_dc.SetBackground(wxBrush(wxColour(0, 0, 0)));
1793 temp_dc.SetFont(m_font);
1794 temp_dc.SetTextForeground(wxColour(255, 255, 255));
1795 temp_dc.DrawText(text, 0, 0);
1796 temp_dc.SelectObject(wxNullBitmap);
1800 wxImage image = bmp.ConvertToImage();
1803 int dx = (x < 0 ? -x : 0);
1804 int dy = (y < 0 ? -y : 0);
1805 w = bmp.GetWidth() - dx;
1806 h = bmp.GetHeight() - dy;
1808 if (w <= 0 || h <= 0)
return;
1809 image = image.GetSubImage(wxRect(dx, dy, w, h));
1814 unsigned char *data =
new unsigned char[w * h * 4];
1815 unsigned char *im = image.GetData();
1818 unsigned int r = m_textforegroundcolour.Red();
1819 unsigned int g = m_textforegroundcolour.Green();
1820 unsigned int b = m_textforegroundcolour.Blue();
1821 for (
int i = 0; i < h; i++) {
1822 for (
int j = 0; j < w; j++) {
1823 unsigned int index = ((i * w) + j) * 4;
1825 data[index + 1] = g;
1826 data[index + 2] = b;
1827 data[index + 3] = im[((i * w) + j) * 3];
1832 unsigned int texobj;
1834 glGenTextures(1, &texobj);
1835 glBindTexture(GL_TEXTURE_2D, texobj);
1837 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1838 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1840 int TextureWidth = NextPow2(w);
1841 int TextureHeight = NextPow2(h);
1842 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TextureWidth, TextureHeight, 0,
1843 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1844 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
1847 glEnable(GL_TEXTURE_2D);
1849 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1851 float u = (float)w / TextureWidth, v = (
float)h / TextureHeight;
1880 shader->SetUniform1i(
"uTex", 0);
1885 mat4x4_rotate_Z(Q, I, 0);
1891 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)Q);
1920 shader->SetAttributePointerf(
"aPos", co1);
1921 shader->SetAttributePointerf(
"aUV", tco1);
1923 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1928 glDisable(GL_BLEND);
1929 glDisable(GL_TEXTURE_2D);
1931 glDeleteTextures(1, &texobj);
1939void ocpnDC::GetTextExtent(
const wxString &
string, wxCoord *w, wxCoord *h,
1940 wxCoord *descent, wxCoord *externalLeading,
1947 dc->GetTextExtent(
string, w, h, descent, externalLeading, font);
1950 if (font) f = *font;
1955 m_texfont.Build(f, 1.0, m_dpi_factor);
1956 m_texfont.GetTextExtent(
string, w, h);
1959 temp_dc.GetTextExtent(
string, w, h, descent, externalLeading, &f);
1963 temp_dc.GetTextExtent(
string, w, h, descent, externalLeading, &f);
1969 if (w && (*w > 500)) *w = 500;
1970 if (h && (*h > 500)) *h = 500;
1973void ocpnDC::ResetBoundingBox() {
1974 if (dc) dc->ResetBoundingBox();
1977void ocpnDC::CalcBoundingBox(wxCoord x, wxCoord y) {
1978 if (dc) dc->CalcBoundingBox(x, y);
1981bool ocpnDC::ConfigurePen() {
1982 if (!m_pen.IsOk())
return false;
1983 if (m_pen == *wxTRANSPARENT_PEN)
return false;
1985 wxColour c = m_pen.GetColour();
1986 int width = m_pen.GetWidth();
1988#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1989 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
1991 glLineWidth(wxMax(g_GLMinSymbolLineWidth, width));
1996bool ocpnDC::ConfigureBrush() {
1997 if (m_brush == wxNullBrush || m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT)
2000 wxColour c = m_brush.GetColour();
2001#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
2002 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
2008void ocpnDC::GLDrawBlendData(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
2009 int format,
const unsigned char *data) {
2011#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
2013 glRasterPos2i(x, y);
2015 glDrawPixels(w, h, format, GL_UNSIGNED_BYTE, data);
2017 glDisable(GL_BLEND);