33#ifndef __OCPN__ANDROID__
47#include <wx/glcanvas.h>
50#include <wx/graphics.h>
51#include <wx/dcclient.h>
57#include "pi_shaders.h"
58#ifdef USE_ANDROID_GLES2
62#ifdef __OCPN__ANDROID__
66extern float g_piGLMinSymbolLineWidth;
67wxArrayPtrVoid pi_gTesselatorVertices;
69#ifdef USE_ANDROID_GLES2
70extern GLint GRIBpi_color_tri_shader_program;
71extern GLint pi_circle_filled_shader_program;
72extern GLint texture_2D_shader_program;
75int NextPow2(
int size) {
88pi_ocpnDC::pi_ocpnDC(wxGLCanvas &canvas)
95#if wxUSE_GRAPHICS_CONTEXT
98 m_textforegroundcolour = wxColour(0, 0, 0);
102 s_odc_tess_work_buf =
nullptr;
104#ifdef USE_ANDROID_GLES2
105 s_odc_tess_vertex_idx = 0;
106 s_odc_tess_vertex_idx_this = 0;
107 s_odc_tess_buf_len = 0;
109 s_odc_tess_work_buf = (GLfloat *)malloc(100 *
sizeof(GLfloat));
110 s_odc_tess_buf_len = 100;
117pi_ocpnDC::pi_ocpnDC(wxDC &pdc)
121 m_brush(wxNullBrush),
123#if wxUSE_GRAPHICS_CONTEXT
125 auto pmdc =
dynamic_cast<wxMemoryDC *
>(dc);
127 pgc = wxGraphicsContext::Create(*pmdc);
129 auto pcdc =
dynamic_cast<wxClientDC *
>(dc);
130 if (pcdc) pgc = wxGraphicsContext::Create(*pcdc);
133 m_textforegroundcolour = wxColour(0, 0, 0);
138 s_odc_tess_work_buf =
nullptr;
142pi_ocpnDC::pi_ocpnDC()
146 m_brush(wxNullBrush),
148#if wxUSE_GRAPHICS_CONTEXT
151 m_textforegroundcolour = wxColour(0, 0, 0);
156 s_odc_tess_work_buf =
nullptr;
161pi_ocpnDC::~pi_ocpnDC() {
162#if wxUSE_GRAPHICS_CONTEXT
167 free(s_odc_tess_work_buf);
174 configureShaders(vp->pix_width, vp->pix_height);
177 m_vpSize = wxSize(vp->pix_width, vp->pix_height);
180void pi_ocpnDC::Clear() {
185 wxBrush tmpBrush = m_brush;
187 SetBrush(wxBrush(glcanvas->GetBackgroundColour()));
188 glcanvas->GetSize(&w, &h);
189 DrawRectangle(0, 0, w, h);
195void pi_ocpnDC::SetBackground(
const wxBrush &brush) {
197 dc->SetBackground(brush);
200 glcanvas->SetBackgroundColour(brush.GetColour());
205void pi_ocpnDC::SetPen(
const wxPen &pen) {
207 if (pen == wxNullPen)
208 dc->SetPen(*wxTRANSPARENT_PEN);
215void pi_ocpnDC::SetBrush(
const wxBrush &brush) {
222void pi_ocpnDC::SetTextForeground(
const wxColour &colour) {
224 dc->SetTextForeground(colour);
226 m_textforegroundcolour = colour;
229void pi_ocpnDC::SetFont(
const wxFont &font) {
236const wxPen &pi_ocpnDC::GetPen()
const {
237 if (dc)
return dc->GetPen();
241const wxBrush &pi_ocpnDC::GetBrush()
const {
242 if (dc)
return dc->GetBrush();
246const wxFont &pi_ocpnDC::GetFont()
const {
247 if (dc)
return dc->GetFont();
251void pi_ocpnDC::GetSize(wxCoord *width, wxCoord *height)
const {
253 dc->GetSize(width, height);
256 glcanvas->GetSize(width, height);
261void pi_ocpnDC::SetGLAttrs(
bool highQuality) {
266 glEnable(GL_LINE_SMOOTH);
267 glEnable(GL_POLYGON_SMOOTH);
270 glDisable(GL_LINE_SMOOTH);
271 glDisable(GL_POLYGON_SMOOTH);
277void pi_ocpnDC::SetGLStipple()
const {
280#ifndef USE_ANDROID_GLES2
281 switch (m_pen.GetStyle()) {
282 case wxPENSTYLE_DOT: {
283 glLineStipple(1, 0x3333);
284 glEnable(GL_LINE_STIPPLE);
287 case wxPENSTYLE_LONG_DASH: {
288 glLineStipple(1, 0xFFF8);
289 glEnable(GL_LINE_STIPPLE);
292 case wxPENSTYLE_SHORT_DASH: {
293 glLineStipple(1, 0x3F3F);
294 glEnable(GL_LINE_STIPPLE);
297 case wxPENSTYLE_DOT_DASH: {
298 glLineStipple(1, 0x8FF1);
299 glEnable(GL_LINE_STIPPLE);
311void piDrawEndCap(
float x1,
float y1,
float t1,
float angle) {
312#ifndef USE_ANDROID_GLES2
313 const int steps = 16;
316 for (
int i = 0; i <= steps; i++) {
317 float a = angle + M_PI / 2 + M_PI / steps * i;
319 float xb = x1 + t1 / 2 * cos(a);
320 float yb = y1 + t1 / 2 * sin(a);
335void piDrawGLThickLine(
float x1,
float y1,
float x2,
float y2, wxPen pen,
339 float angle = atan2f(y2 - y1, x2 - x1);
340 float t1 = pen.GetWidth();
341 float t2sina1 = t1 / 2 * sinf(angle);
342 float t2cosa1 = t1 / 2 * cosf(angle);
344#ifndef USE_ANDROID_GLES2
345 glBegin(GL_TRIANGLES);
350 int n_dashes = pen.GetDashes(&dashes);
352 float lpix = sqrtf(powf((
float)(x1 - x2), 2) + powf((
float)(y1 - y2), 2));
356 float ldraw = t1 * dashes[0];
357 float lspace = t1 * dashes[1];
359 while (lrun < lpix) {
361 float xb = xa + ldraw * cosf(angle);
362 float yb = ya + ldraw * sinf(angle);
364 if ((lrun + ldraw) >= lpix)
370 glVertex2f(xa + t2sina1, ya - t2cosa1);
371 glVertex2f(xb + t2sina1, yb - t2cosa1);
372 glVertex2f(xb - t2sina1, yb + t2cosa1);
374 glVertex2f(xb - t2sina1, yb + t2cosa1);
375 glVertex2f(xa - t2sina1, ya + t2cosa1);
376 glVertex2f(xa + t2sina1, ya - t2cosa1);
383 xb = xa + lspace * cos(angle);
384 yb = ya + lspace * sin(angle);
391 glVertex2f(x1 + t2sina1, y1 - t2cosa1);
392 glVertex2f(x2 + t2sina1, y2 - t2cosa1);
393 glVertex2f(x2 - t2sina1, y2 + t2cosa1);
395 glVertex2f(x2 - t2sina1, y2 + t2cosa1);
396 glVertex2f(x1 - t2sina1, y1 + t2cosa1);
397 glVertex2f(x1 + t2sina1, y1 - t2cosa1);
401 if (pen.GetCap() == wxCAP_ROUND) {
402 piDrawEndCap(x1, y1, t1, angle);
403 piDrawEndCap(x2, y2, t1, angle + M_PI);
413 int n_dashes = pen.GetDashes(&dashes);
415 float lpix = sqrtf(powf((
float)(x1 - x2), 2) + powf((
float)(y1 - y2), 2));
419 float ldraw = t1 * dashes[0];
420 float lspace = t1 * dashes[1];
422 glUseProgram(GRIBpi_color_tri_shader_program);
427 glBindBuffer(GL_ARRAY_BUFFER, 0);
428 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
431 glGetAttribLocation(GRIBpi_color_tri_shader_program,
"position");
432 glEnableVertexAttribArray(pos);
433 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float), vert);
439 GLint matloc = glGetUniformLocation(GRIBpi_color_tri_shader_program,
441 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)I);
443 wxColor c = pen.GetColour();
445 colorv[0] = c.Red() / float(256);
446 colorv[1] = c.Green() / float(256);
447 colorv[2] = c.Blue() / float(256);
448 colorv[3] = c.Alpha() / float(256);
451 glGetUniformLocation(GRIBpi_color_tri_shader_program,
"color");
452 glUniform4fv(colloc, 1, colorv);
454 while (lrun < lpix) {
456 float xb = xa + ldraw * cosf(angle);
457 float yb = ya + ldraw * sinf(angle);
459 if ((lrun + ldraw) >= lpix)
465 vert[0] = xa + t2sina1;
466 vert[1] = ya - t2cosa1;
467 vert[2] = xb + t2sina1;
468 vert[3] = yb - t2cosa1;
469 vert[4] = xb - t2sina1;
470 vert[5] = yb + t2cosa1;
471 vert[6] = xb - t2sina1;
472 vert[7] = yb + t2cosa1;
473 vert[8] = xa - t2sina1;
474 vert[9] = ya + t2cosa1;
475 vert[10] = xa + t2sina1;
476 vert[11] = ya - t2cosa1;
478 glDrawArrays(GL_TRIANGLES, 0, 6);
485 xb = xa + lspace * cos(angle);
486 yb = ya + lspace * sin(angle);
494 vert[0] = x1 + t2sina1;
495 vert[1] = y1 - t2cosa1;
496 vert[2] = x2 + t2sina1;
497 vert[3] = y2 - t2cosa1;
498 vert[4] = x2 - t2sina1;
499 vert[5] = y2 + t2cosa1;
500 vert[6] = x2 - t2sina1;
501 vert[7] = y2 + t2cosa1;
502 vert[8] = x1 - t2sina1;
503 vert[9] = y1 + t2cosa1;
504 vert[10] = x1 + t2sina1;
505 vert[11] = y1 - t2cosa1;
507 glUseProgram(GRIBpi_color_tri_shader_program);
510 glBindBuffer(GL_ARRAY_BUFFER, 0);
511 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
514 glGetAttribLocation(GRIBpi_color_tri_shader_program,
"position");
515 glEnableVertexAttribArray(pos);
516 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float), vert);
522 GLint matloc = glGetUniformLocation(GRIBpi_color_tri_shader_program,
524 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)I);
526 wxColor c = pen.GetColour();
528 colorv[0] = c.Red() / float(256);
529 colorv[1] = c.Green() / float(256);
530 colorv[2] = c.Blue() / float(256);
531 colorv[3] = c.Alpha() / float(256);
534 glGetUniformLocation(GRIBpi_color_tri_shader_program,
"color");
535 glUniform4fv(colloc, 1, colorv);
537 glDrawArrays(GL_TRIANGLES, 0, 6);
538 glDisableVertexAttribArray(pos);
555void pi_ocpnDC::DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2,
557 if (dc) dc->DrawLine(x1, y1, x2, y2);
559 else if (ConfigurePen()) {
560 bool b_draw_thick =
false;
562 float pen_width = wxMax(g_piGLMinSymbolLineWidth, m_pen.GetWidth());
570 glEnable(GL_LINE_SMOOTH);
573 if (pen_width > 1.0) {
575 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
576 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
577 if (pen_width > parms[1])
580 glLineWidth(pen_width);
582 glLineWidth(pen_width);
586 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
587 if (pen_width > parms[1])
590 glLineWidth(pen_width);
592 glLineWidth(pen_width);
597 piDrawGLThickLine(x1, y1, x2, y2, m_pen, b_hiqual);
599 glUseProgram(GRIBpi_color_tri_shader_program);
603 glGetAttribLocation(GRIBpi_color_tri_shader_program,
"position");
604 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float),
606 glEnableVertexAttribArray(pos);
614 colorv[0] = m_pen.GetColour().Red() / float(256);
615 colorv[1] = m_pen.GetColour().Green() / float(256);
616 colorv[2] = m_pen.GetColour().Blue() / float(256);
620 glGetUniformLocation(GRIBpi_color_tri_shader_program,
"color");
621 glUniform4fv(colloc, 1, colorv);
624 int n_dashes = m_pen.GetDashes(&dashes);
626 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
627 float cosa = cosf(angle);
628 float sina = sinf(angle);
629 float t1 = m_pen.GetWidth();
631 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
635 float ldraw = t1 * dashes[0];
636 float lspace = t1 * dashes[1];
638 ldraw = wxMax(ldraw, 4.0);
639 lspace = wxMax(lspace, 4.0);
640 lpix = wxMin(lpix, 2000.0);
642 while (lrun < lpix) {
644 float xb = xa + ldraw * cosa;
645 float yb = ya + ldraw * sina;
647 if ((lrun + ldraw) >= lpix)
658 glDrawArrays(GL_LINES, 0, 2);
659 glDisableVertexAttribArray(pos);
661 xa = xa + (lspace + ldraw) * cosa;
662 ya = ya + (lspace + ldraw) * sina;
663 lrun += lspace + ldraw;
672 glDrawArrays(GL_LINES, 0, 2);
673 glDisableVertexAttribArray(pos);
681 piDrawGLThickLine(x1, y1, x2, y2, m_pen, b_hiqual);
684 int n_dashes = m_pen.GetDashes(&dashes);
686 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
687 float cosa = cosf(angle);
688 float sina = sinf(angle);
689 float t1 = m_pen.GetWidth();
691 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
695 float ldraw = t1 * dashes[0];
696 float lspace = t1 * dashes[1];
698 ldraw = wxMax(ldraw, 4.0);
699 lspace = wxMax(lspace, 4.0);
700 lpix = wxMin(lpix, 2000.0);
703 while (lrun < lpix) {
705 float xb = xa + ldraw * cosa;
706 float yb = ya + ldraw * sina;
708 if ((lrun + ldraw) >= lpix)
717 xa = xa + (lspace + ldraw) * cosa;
718 ya = ya + (lspace + ldraw) * sina;
719 lrun += lspace + ldraw;
731 glDisable(GL_LINE_STIPPLE);
734 glDisable(GL_LINE_SMOOTH);
742void piDrawGLThickLines(
int n, wxPoint points[], wxCoord xoffset,
743 wxCoord yoffset, wxPen pen,
bool b_hiqual) {
747#ifdef USE_ANDROID_GLES2
748 wxPoint p0 = points[0];
749 for (
int i = 1; i < n; i++) {
750 piDrawGLThickLine(p0.x + xoffset, p0.y + yoffset, points[i].x + xoffset,
751 points[i].y + yoffset, pen, b_hiqual);
759 if (pen.GetDashes(&dashes)) {
760 wxPoint p0 = points[0];
761 for (
int i = 1; i < n; i++) {
762 piDrawGLThickLine(p0.x + xoffset, p0.y + yoffset, points[i].x + xoffset,
763 points[i].y + yoffset, pen, b_hiqual);
770 wxPoint *cpoints =
new wxPoint[n];
771 cpoints[0] = points[0];
773 for (
int i = 1; i < n; i++) {
774 if (points[i].x != points[i - 1].x || points[i].y != points[i - 1].y)
775 cpoints[c++] = points[i];
782 float t1 = pen.GetWidth();
784 float x0 = cpoints[0].x, y0 = cpoints[0].y, x1 = cpoints[1].x,
786 float a0 = atan2f(y1 - y0, x1 - x0);
790 glBegin(GL_TRIANGLES);
792 float t2sina0 = t1 / 2 * sinf(a0);
793 float t2cosa0 = t1 / 2 * cosf(a0);
795 for (
int i = 1; i < c; i++) {
800 x2 = cpoints[i + 1].x, y2 = cpoints[i + 1].y;
801 a1 = atan2f(y2 - y1, x2 - x1);
807 float aa = (a0 + a1) / 2;
808 float diff = fabsf(a0 - a1);
809 if (diff > M_PI) diff -= 2 * (float)M_PI;
810 float rad = t1 / 2 / wxMax(cosf(diff / 2), .4);
812 float t2sina1 = rad * sinf(aa);
813 float t2cosa1 = rad * cosf(aa);
815 glVertex2f(x1 + t2sina1, y1 - t2cosa1);
816 glVertex2f(x1 - t2sina1, y1 + t2cosa1);
817 glVertex2f(x0 + t2sina0, y0 - t2cosa0);
819 glVertex2f(x0 - t2sina0, y0 + t2cosa0);
820 glVertex2f(x0 + t2sina0, y0 - t2cosa0);
822 float dot = t2sina0 * t2sina1 + t2cosa0 * t2cosa1;
824 glVertex2f(x1 - t2sina1, y1 + t2cosa1);
826 glVertex2f(x1 + t2sina1, y1 - t2cosa1);
831 t2sina0 = t2sina1, t2cosa0 = t2cosa1;
834 if (pen.GetCap() == wxCAP_ROUND) {
835 piDrawEndCap(x0, y0, t1, a0);
836 piDrawEndCap(x0, y0, t1, a0 + M_PI);
848void pi_ocpnDC::DrawLines(
int n, wxPoint points[], wxCoord xoffset,
849 wxCoord yoffset,
bool b_hiqual) {
850 if (dc) dc->DrawLines(n, points, xoffset, yoffset);
852 else if (ConfigurePen()) {
857 SetGLAttrs(b_hiqual);
859 bool b_draw_thick =
false;
861 glDisable(GL_LINE_STIPPLE);
867 if (m_pen.GetWidth() > 1) {
869 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
870 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
872 if (m_pen.GetWidth() > parms[1])
875 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, m_pen.GetWidth()));
877 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, 1));
879 if (m_pen.GetWidth() > 1) {
881 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
882 if (m_pen.GetWidth() > parms[1])
885 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, m_pen.GetWidth()));
887 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, 1));
891 piDrawGLThickLines(n, points, xoffset, yoffset, m_pen, b_hiqual);
894 glDisable(GL_LINE_STIPPLE);
895 glDisable(GL_POLYGON_SMOOTH);
904 glBegin(GL_LINE_STRIP);
905 for (
int i = 0; i < n; i++)
906 glVertex2i(points[i].x + xoffset, points[i].y + yoffset);
912 if (workBufSize < (
size_t)n * 2) {
913 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
917 for (
int i = 0; i < n; i++) {
918 workBuf[i * 2] = points[i].x + xoffset;
919 workBuf[(i * 2) + 1] = points[i].y + yoffset;
922 glUseProgram(GRIBpi_color_tri_shader_program);
925 glGetAttribLocation(GRIBpi_color_tri_shader_program,
"position");
926 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float),
928 glEnableVertexAttribArray(pos);
935 colorv[0] = m_pen.GetColour().Red() / float(256);
936 colorv[1] = m_pen.GetColour().Green() / float(256);
937 colorv[2] = m_pen.GetColour().Blue() / float(256);
938 colorv[3] = m_pen.GetColour().Alpha() / float(256);
942 glGetUniformLocation(GRIBpi_color_tri_shader_program,
"color");
943 glUniform4fv(colloc, 1, colorv);
945 glDrawArrays(GL_LINE_STRIP, 0, n);
946 glDisableVertexAttribArray(pos);
953 glDisable(GL_LINE_STIPPLE);
954 glDisable(GL_POLYGON_SMOOTH);
961void pi_ocpnDC::StrokeLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) {
962#if wxUSE_GRAPHICS_CONTEXT
964 pgc->SetPen(dc->GetPen());
965 pgc->StrokeLine(x1, y1, x2, y2);
967 dc->CalcBoundingBox(x1, y1);
968 dc->CalcBoundingBox(x2, y2);
971 DrawLine(x1, y1, x2, y2,
true);
974void pi_ocpnDC::StrokeLines(
int n, wxPoint *points) {
978#if wxUSE_GRAPHICS_CONTEXT
980 wxPoint2DDouble *dPoints =
981 (wxPoint2DDouble *)malloc(n *
sizeof(wxPoint2DDouble));
982 for (
int i = 0; i < n; i++) {
983 dPoints[i].m_x = points[i].x;
984 dPoints[i].m_y = points[i].y;
986 pgc->SetPen(dc->GetPen());
987 pgc->StrokeLines(n, dPoints);
991 DrawLines(n, points, 0, 0,
true);
994void pi_ocpnDC::DrawGLLineArray(
int n,
float *vertex_array,
float *color_array,
995 unsigned char *color_array_ub,
bool b_hiqual) {
999 if (ConfigurePen()) {
1004 SetGLAttrs(b_hiqual);
1006 bool b_draw_thick =
false;
1008 glDisable(GL_LINE_STIPPLE);
1014 if (m_pen.GetWidth() > 1) {
1020 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, m_pen.GetWidth()));
1022 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, 1));
1024 if (m_pen.GetWidth() > 1) {
1027 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, m_pen.GetWidth()));
1029 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, 1));
1034 glEnableClientState(GL_VERTEX_ARRAY);
1035 glEnableClientState(GL_COLOR_ARRAY);
1037 glColorPointer(4, GL_UNSIGNED_BYTE, 4 *
sizeof(
unsigned char),
1039 glVertexPointer(2, GL_FLOAT, 2 *
sizeof(
float), vertex_array);
1040 glDrawArrays(GL_LINES, 0, n);
1042 glDisableClientState(GL_VERTEX_ARRAY);
1043 glDisableClientState(GL_COLOR_ARRAY);
1052 glUseProgram(GRIBpi_colorv_tri_shader_program);
1055 glGetAttribLocation(GRIBpi_colorv_tri_shader_program,
"position");
1056 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float),
1058 glEnableVertexAttribArray(pos);
1061 glGetAttribLocation(GRIBpi_colorv_tri_shader_program,
"colorv");
1062 glVertexAttribPointer(colloc, 4, GL_FLOAT, GL_FALSE, 4 *
sizeof(
float),
1064 glEnableVertexAttribArray(colloc);
1066 glDrawArrays(GL_LINES, 0, n);
1067 glDisableVertexAttribArray(pos);
1068 glDisableVertexAttribArray(colloc);
1075 glDisable(GL_LINE_STIPPLE);
1076 glDisable(GL_POLYGON_SMOOTH);
1077 glDisable(GL_BLEND);
1083void pi_ocpnDC::DrawRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h) {
1084 if (dc) dc->DrawRectangle(x, y, w, h);
1088 if (ConfigureBrush()) {
1091 glVertex2i(x + w, y);
1092 glVertex2i(x + w, y + h);
1093 glVertex2i(x, y + h);
1097 if (ConfigurePen()) {
1098 glBegin(GL_LINE_LOOP);
1100 glVertex2i(x + w, y);
1101 glVertex2i(x + w, y + h);
1102 glVertex2i(x, y + h);
1106 DrawRoundedRectangle(x, y, w, h, 0);
1114static void drawrrhelper(wxCoord x0, wxCoord y0, wxCoord r,
int quadrant,
1117#ifndef USE_ANDROID_GLES2
1118 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
1122 x = r, y = 0, dx = 0, dy = -rs, ddx = -rss, ddy = rss;
1125 x = 0, y = -r, dx = -rs, dy = 0, ddx = rss, ddy = rss;
1128 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
1131 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
1137 for (
int i = 0; i < steps; i++) {
1138 glVertex2i(x0 + floor(x), y0 + floor(y));
1139 x += dx + ddx / 2, y += dy + ddy / 2;
1140 dx += ddx, dy += ddy;
1142 glVertex2i(x0 + floor(x), y0 + floor(y));
1147void pi_ocpnDC::drawrrhelperGLES2(wxCoord x0, wxCoord y0, wxCoord r,
1148 int quadrant,
int steps) {
1150 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
1154 x = r, y = 0, dx = 0, dy = -rs, ddx = -rss, ddy = rss;
1157 x = 0, y = -r, dx = -rs, dy = 0, ddx = rss, ddy = rss;
1160 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
1163 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
1169 for (
int i = 0; i < steps; i++) {
1170 workBuf[workBufIndex++] = x0 + floor(x);
1171 workBuf[workBufIndex++] = y0 + floor(y);
1173 x += dx + ddx / 2, y += dy + ddy / 2;
1174 dx += ddx, dy += ddy;
1177 workBuf[workBufIndex++] = x0 + floor(x);
1178 workBuf[workBufIndex++] = y0 + floor(y);
1182void pi_ocpnDC::DrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
1184 if (dc) dc->DrawRoundedRectangle(x, y, w, h, r);
1188 int steps = ceil(sqrt((
float)r));
1190 wxCoord x1 = x + r, x2 = x + w - r;
1191 wxCoord y1 = y + r, y2 = y + h - r;
1196 size_t bufReq = steps * 8 * 2 *
sizeof(float);
1198 if (workBufSize < bufReq) {
1199 workBuf = (
float *)realloc(workBuf, bufReq);
1200 workBufSize = bufReq;
1204 drawrrhelperGLES2(x2, y1, r, 0, steps);
1205 drawrrhelperGLES2(x1, y1, r, 1, steps);
1206 drawrrhelperGLES2(x1, y2, r, 2, steps);
1207 drawrrhelperGLES2(x2, y2, r, 3, steps);
1209 glUseProgram(GRIBpi_color_tri_shader_program);
1213 glGetAttribLocation(GRIBpi_color_tri_shader_program,
"position");
1216 glBindBuffer(GL_ARRAY_BUFFER, 0);
1217 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1219 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, workBuf);
1220 glEnableVertexAttribArray(mPosAttrib);
1224 bcolorv[0] = m_brush.GetColour().Red() / float(256);
1225 bcolorv[1] = m_brush.GetColour().Green() / float(256);
1226 bcolorv[2] = m_brush.GetColour().Blue() / float(256);
1227 bcolorv[3] = m_brush.GetColour().Alpha() / float(256);
1230 glGetUniformLocation(GRIBpi_color_tri_shader_program,
"color");
1231 glUniform4fv(bcolloc, 1, bcolorv);
1240 mat4x4_rotate_Z(Q, I, angle);
1246 GLint matloc = glGetUniformLocation(GRIBpi_color_tri_shader_program,
1248 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)Q);
1251 glDrawArrays(GL_TRIANGLE_FAN, 0, workBufIndex / 2);
1252 glDisableVertexAttribArray(mPosAttrib);
1256 mat4x4_identity(IM);
1257 GLint matlocf = glGetUniformLocation(GRIBpi_color_tri_shader_program,
1259 glUniformMatrix4fv(matlocf, 1, GL_FALSE, (
const GLfloat *)IM);
1263 if (ConfigureBrush()) {
1264 glBegin(GL_TRIANGLE_FAN);
1265 drawrrhelper(x2, y1, r, 0, steps);
1266 drawrrhelper(x1, y1, r, 1, steps);
1267 drawrrhelper(x1, y2, r, 2, steps);
1268 drawrrhelper(x2, y2, r, 3, steps);
1272 if (ConfigurePen()) {
1273 glBegin(GL_LINE_LOOP);
1274 drawrrhelper(x2, y1, r, 0, steps);
1275 drawrrhelper(x1, y1, r, 1, steps);
1276 drawrrhelper(x1, y2, r, 2, steps);
1277 drawrrhelper(x2, y2, r, 3, steps);
1285void pi_ocpnDC::DrawCircle(wxCoord x, wxCoord y, wxCoord radius) {
1286#ifdef USE_ANDROID_GLES2
1292 coords[0] = x - radius;
1293 coords[1] = y + radius;
1294 coords[2] = x + radius;
1295 coords[3] = y + radius;
1296 coords[4] = x - radius;
1297 coords[5] = y - radius;
1298 coords[6] = x + radius;
1299 coords[7] = y - radius;
1301 glUseProgram(pi_circle_filled_shader_program);
1305 glGetAttribLocation(pi_circle_filled_shader_program,
"aPos");
1308 glBindBuffer(GL_ARRAY_BUFFER, 0);
1309 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1311 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, coords);
1312 glEnableVertexAttribArray(mPosAttrib);
1316 glGetUniformLocation(pi_circle_filled_shader_program,
"circle_radius");
1317 glUniform1f(radiusloc, radius);
1321 glGetUniformLocation(pi_circle_filled_shader_program,
"circle_center");
1324 ctrv[1] = m_vpSize.y - y;
1325 glUniform2fv(centerloc, 1, ctrv);
1329 colorv[0] = m_brush.GetColour().Red() / float(256);
1330 colorv[1] = m_brush.GetColour().Green() / float(256);
1331 colorv[2] = m_brush.GetColour().Blue() / float(256);
1332 colorv[3] = (m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT) ? 0.0 : 1.0;
1335 glGetUniformLocation(pi_circle_filled_shader_program,
"circle_color");
1336 glUniform4fv(colloc, 1, colorv);
1340 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1341 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1342 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1343 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1346 glGetUniformLocation(pi_circle_filled_shader_program,
"border_color");
1347 glUniform4fv(bcolloc, 1, bcolorv);
1350 GLint borderWidthloc =
1351 glGetUniformLocation(pi_circle_filled_shader_program,
"border_width");
1352 glUniform1f(borderWidthloc, m_pen.GetWidth());
1360 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1361 glDisableVertexAttribArray(mPosAttrib);
1364 glDisable(GL_BLEND);
1367 DrawEllipse(x - radius, y - radius, 2 * radius, 2 * radius);
1371void pi_ocpnDC::StrokeCircle(wxCoord x, wxCoord y, wxCoord radius) {
1372#if wxUSE_GRAPHICS_CONTEXT
1374 wxGraphicsPath gpath = pgc->CreatePath();
1375 gpath.AddCircle(x, y, radius);
1377 pgc->SetPen(GetPen());
1378 pgc->SetBrush(GetBrush());
1379 pgc->DrawPath(gpath);
1382 dc->CalcBoundingBox(x + radius + 2, y + radius + 2);
1383 dc->CalcBoundingBox(x - radius - 2, y - radius - 2);
1386 DrawCircle(x, y, radius);
1389void pi_ocpnDC::DrawEllipse(wxCoord x, wxCoord y, wxCoord width,
1391 if (dc) dc->DrawEllipse(x, y, width, height);
1394 float r1 = width / 2, r2 = height / 2;
1395 float cx = x + r1, cy = y + r2;
1401 float steps = floorf(
1402 wxMax(sqrtf(sqrtf((
float)(width * width + height * height))), 1) *
1405#ifndef USE_ANDROID_GLES2
1406 if (ConfigureBrush()) {
1407 glBegin(GL_TRIANGLE_FAN);
1409 for (
float a = 0; a <= 2 * M_PI + M_PI / steps; a += 2 * M_PI / steps)
1410 glVertex2f(cx + r1 * sinf(a), cy + r2 * cosf(a));
1414 if (ConfigurePen()) {
1415 glBegin(GL_LINE_LOOP);
1416 for (
float a = 0; a < 2 * M_PI - M_PI / steps; a += 2 * M_PI / steps)
1417 glVertex2f(cx + r1 * sinf(a), cy + r2 * cosf(a));
1422 glDisable(GL_BLEND);
1427void pi_ocpnDC::DrawPolygon(
int n, wxPoint points[], wxCoord xoffset,
1428 wxCoord yoffset,
float scale,
float angle) {
1429 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1439#ifdef USE_ANDROID_GLES2
1444 DrawPolygonTessellated(n, points, xoffset, yoffset);
1448 if (workBufSize < (
size_t)n * 2) {
1449 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
1450 workBufSize = n * 4;
1453 for (
int i = 0; i < n; i++) {
1454 workBuf[i * 2] = (points[i].x *
scale);
1455 workBuf[i * 2 + 1] = (points[i].y *
scale);
1458 glUseProgram(GRIBpi_color_tri_shader_program);
1462 glGetAttribLocation(GRIBpi_color_tri_shader_program,
"position");
1465 glBindBuffer(GL_ARRAY_BUFFER, 0);
1466 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1468 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, workBuf);
1469 glEnableVertexAttribArray(mPosAttrib);
1473 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1474 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1475 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1476 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1479 glGetUniformLocation(GRIBpi_color_tri_shader_program,
"color");
1480 glUniform4fv(bcolloc, 1, bcolorv);
1485 mat4x4_rotate_Z(Q, I, angle);
1491 GLint matloc = glGetUniformLocation(GRIBpi_color_tri_shader_program,
1493 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)Q);
1496 glDrawArrays(GL_LINE_LOOP, 0, n);
1499 bcolorv[0] = m_brush.GetColour().Red() / float(256);
1500 bcolorv[1] = m_brush.GetColour().Green() / float(256);
1501 bcolorv[2] = m_brush.GetColour().Blue() / float(256);
1502 bcolorv[3] = m_brush.GetColour().Alpha() / float(256);
1504 glUniform4fv(bcolloc, 1, bcolorv);
1509 float x1 = workBuf[4];
1510 float y1 = workBuf[5];
1511 workBuf[4] = workBuf[6];
1512 workBuf[5] = workBuf[7];
1516 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1517 }
else if (n == 3) {
1518 glDrawArrays(GL_TRIANGLES, 0, 3);
1521 glDisableVertexAttribArray(mPosAttrib);
1525 mat4x4_identity(IM);
1526 GLint matlocf = glGetUniformLocation(GRIBpi_color_tri_shader_program,
1528 glUniformMatrix4fv(matlocf, 1, GL_FALSE, (
const GLfloat *)IM);
1535 if (ConfigureBrush()) {
1536 glEnable(GL_POLYGON_SMOOTH);
1537 glBegin(GL_POLYGON);
1538 for (
int i = 0; i < n; i++)
1539 glVertex2f((points[i].x *
scale) + xoffset,
1540 (points[i].y *
scale) + yoffset);
1542 glDisable(GL_POLYGON_SMOOTH);
1545 if (ConfigurePen()) {
1546 glEnable(GL_LINE_SMOOTH);
1547 glBegin(GL_LINE_LOOP);
1548 for (
int i = 0; i < n; i++)
1549 glVertex2f((points[i].x *
scale) + xoffset,
1550 (points[i].y *
scale) + yoffset);
1552 glDisable(GL_LINE_SMOOTH);
1578void APIENTRY pi_ocpnDCcombineCallback(GLdouble coords[3],
1579 GLdouble *vertex_data[4],
1580 GLfloat weight[4], GLdouble **dataOut) {
1583 vertex =
new GLvertex();
1584 pi_gTesselatorVertices.Add(vertex);
1586 vertex->info.x = coords[0];
1587 vertex->info.y = coords[1];
1588 vertex->info.z = coords[2];
1590 for (
int i = 3; i < 6; i++) {
1592 weight[0] * vertex_data[0][i] + weight[1] * vertex_data[1][i];
1595 *dataOut = &(vertex->data[0]);
1598void APIENTRY ocpnDCvertexCallback(GLvoid *arg) {
1600 vertex = (GLvertex *)arg;
1601 glVertex2f((
float)vertex->info.x, (
float)vertex->info.y);
1604void APIENTRY ocpnDCerrorCallback(GLenum errorCode) {
1605 const GLubyte *estring;
1606 estring = gluErrorString(errorCode);
1610void APIENTRY ocpnDCbeginCallback(GLenum type) { glBegin(type); }
1612void APIENTRY ocpnDCendCallback() { glEnd(); }
1619static std::list<double *> odc_combine_work_data;
1620static void pi_odc_combineCallbackD(GLdouble coords[3],
1621 GLdouble *vertex_data[4], GLfloat weight[4],
1622 GLdouble **dataOut,
void *data) {
1629void pi_odc_vertexCallbackD_GLSL(GLvoid *vertex,
void *data) {
1633 if (pDC->s_odc_tess_vertex_idx > pDC->s_odc_tess_buf_len - 8) {
1634 int new_buf_len = pDC->s_odc_tess_buf_len + 100;
1635 GLfloat *tmp = pDC->s_odc_tess_work_buf;
1637 pDC->s_odc_tess_work_buf = (GLfloat *)realloc(
1638 pDC->s_odc_tess_work_buf, new_buf_len *
sizeof(GLfloat));
1639 if (
nullptr == pDC->s_odc_tess_work_buf) {
1643 pDC->s_odc_tess_buf_len = new_buf_len;
1646 GLdouble *pointer = (GLdouble *)vertex;
1648 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[0];
1649 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[1];
1651 pDC->s_odc_nvertex++;
1654void pi_odc_beginCallbackD_GLSL(GLenum mode,
void *data) {
1656 pDC->s_odc_tess_vertex_idx_this = pDC->s_odc_tess_vertex_idx;
1657 pDC->s_odc_tess_mode = mode;
1658 pDC->s_odc_nvertex = 0;
1661void pi_odc_endCallbackD_GLSL(
void *data) {
1667 glUseProgram(GRIBpi_color_tri_shader_program);
1670 glBindBuffer(GL_ARRAY_BUFFER, 0);
1671 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1673 float *bufPt = &(pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx_this]);
1674 GLint pos = glGetAttribLocation(GRIBpi_color_tri_shader_program,
"position");
1675 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float), bufPt);
1676 glEnableVertexAttribArray(pos);
1684 wxColour c = pDC->GetBrush().GetColour();
1686 colorv[0] = c.Red() / float(256);
1687 colorv[1] = c.Green() / float(256);
1688 colorv[2] = c.Blue() / float(256);
1689 colorv[3] = c.Alpha() / float(256);
1691 GLint colloc = glGetUniformLocation(GRIBpi_color_tri_shader_program,
"color");
1692 glUniform4fv(colloc, 1, colorv);
1694 glDrawArrays(pDC->s_odc_tess_mode, 0, pDC->s_odc_nvertex);
1696 glDisableVertexAttribArray(pos);
1705void pi_ocpnDC::DrawPolygonTessellated(
int n, wxPoint points[], wxCoord xoffset,
1707 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1710#if !defined(ocpnUSE_GLES) || \
1711 defined(USE_ANDROID_GLES2)
1715 DrawPolygon(n, points, xoffset, yoffset);
1720 m_tobj = gluNewTess();
1721 s_odc_tess_vertex_idx = 0;
1723 gluTessCallback(m_tobj, GLU_TESS_VERTEX_DATA,
1724 (_GLUfuncptr)&pi_odc_vertexCallbackD_GLSL);
1725 gluTessCallback(m_tobj, GLU_TESS_BEGIN_DATA,
1726 (_GLUfuncptr)&pi_odc_beginCallbackD_GLSL);
1727 gluTessCallback(m_tobj, GLU_TESS_END_DATA,
1728 (_GLUfuncptr)&pi_odc_endCallbackD_GLSL);
1729 gluTessCallback(m_tobj, GLU_TESS_COMBINE_DATA,
1730 (_GLUfuncptr)&pi_odc_combineCallbackD);
1733 gluTessNormal(m_tobj, 0, 0, 1);
1734 gluTessProperty(m_tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
1736 if (ConfigureBrush()) {
1737 gluTessBeginPolygon(m_tobj,
this);
1738 gluTessBeginContour(m_tobj);
1740 for (
int i = 0; i < n; i++) {
1741 double *p =
new double[6];
1742 p[0] = points[i].x, p[1] = points[i].y, p[2] = 0;
1743 gluTessVertex(m_tobj, p, p);
1746 gluTessEndContour(m_tobj);
1747 gluTessEndPolygon(m_tobj);
1750 gluDeleteTess(m_tobj);
1759 static GLUtesselator *tobj =
nullptr;
1760 if (!tobj) tobj = gluNewTess();
1762 gluTessCallback(tobj, GLU_TESS_VERTEX, (_GLUfuncptr)&ocpnDCvertexCallback);
1763 gluTessCallback(tobj, GLU_TESS_BEGIN, (_GLUfuncptr)&ocpnDCbeginCallback);
1764 gluTessCallback(tobj, GLU_TESS_END, (_GLUfuncptr)&ocpnDCendCallback);
1765 gluTessCallback(tobj, GLU_TESS_COMBINE,
1766 (_GLUfuncptr)&pi_ocpnDCcombineCallback);
1767 gluTessCallback(tobj, GLU_TESS_ERROR, (_GLUfuncptr)&ocpnDCerrorCallback);
1769 gluTessNormal(tobj, 0, 0, 1);
1770 gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
1772 if (ConfigureBrush()) {
1773 gluTessBeginPolygon(tobj,
nullptr);
1774 gluTessBeginContour(tobj);
1776 for (
int i = 0; i < n; i++) {
1777 GLvertex *vertex =
new GLvertex();
1778 pi_gTesselatorVertices.Add(vertex);
1779 vertex->info.x = (GLdouble)points[i].x;
1780 vertex->info.y = (GLdouble)points[i].y;
1781 vertex->info.z = (GLdouble)0.0;
1782 vertex->info.r = (GLdouble)0.0;
1783 vertex->info.g = (GLdouble)0.0;
1784 vertex->info.b = (GLdouble)0.0;
1785 gluTessVertex(tobj, (GLdouble *)vertex, (GLdouble *)vertex);
1787 gluTessEndContour(tobj);
1788 gluTessEndPolygon(tobj);
1791 for (
unsigned int i = 0; i < pi_gTesselatorVertices.Count(); i++)
1792 delete (GLvertex *)pi_gTesselatorVertices.Item(i);
1793 pi_gTesselatorVertices.Clear();
1795 gluDeleteTess(tobj);
1801void pi_ocpnDC::StrokePolygon(
int n, wxPoint points[], wxCoord xoffset,
1802 wxCoord yoffset,
float scale) {
1803#if wxUSE_GRAPHICS_CONTEXT
1805 wxGraphicsPath gpath = pgc->CreatePath();
1806 gpath.MoveToPoint(points[0].x + xoffset, points[0].y + yoffset);
1807 for (
int i = 1; i < n; i++)
1808 gpath.AddLineToPoint(points[i].x + xoffset, points[i].y + yoffset);
1809 gpath.AddLineToPoint(points[0].x + xoffset, points[0].y + yoffset);
1811 pgc->SetPen(GetPen());
1812 pgc->SetBrush(GetBrush());
1813 pgc->DrawPath(gpath);
1815 for (
int i = 0; i < n; i++)
1816 dc->CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset);
1819 DrawPolygon(n, points, xoffset, yoffset,
scale);
1822void pi_ocpnDC::DrawBitmap(
const wxBitmap &bitmap, wxCoord x, wxCoord y,
1825 if (x < 0 || y < 0) {
1826 int dx = (x < 0 ? -x : 0);
1827 int dy = (y < 0 ? -y : 0);
1828 int w = bitmap.GetWidth() - dx;
1829 int h = bitmap.GetHeight() - dy;
1831 if (w <= 0 || h <= 0)
return;
1832 wxBitmap newBitmap = bitmap.GetSubBitmap(wxRect(dx, dy, w, h));
1839 if (dc) dc->DrawBitmap(bmp, x, y, usemask);
1847#ifndef USE_ANDROID_GLES2
1848 wxImage image = bmp.ConvertToImage();
1849 int w = image.GetWidth(), h = image.GetHeight();
1852 unsigned char *d = image.GetData();
1853 unsigned char *a = image.GetAlpha();
1855 unsigned char mr, mg, mb;
1856 if (!image.GetOrFindMaskColour(&mr, &mg, &mb) && !a) {
1857 printf(
"trying to use mask to draw a bitmap without alpha or mask\n");
1861 if (image.HasMask()) a = 0;
1864 unsigned char *e =
new unsigned char[4 * w * h];
1866 for (
int y = 0; y < h; y++)
1867 for (
int x = 0; x < w; x++) {
1868 unsigned char r, g, b;
1869 int off = (y * image.GetWidth() + x);
1879 a ? a[off] : ((r == mr) && (g == mg) && (b == mb) ? 0 : 255);
1885 glColor4f(1, 1, 1, 1);
1886 GLDrawBlendData(x, y, w, h, GL_RGBA, e);
1889 glRasterPos2i(x, y);
1891 if (image.GetData())
1892 glDrawPixels(w, h, GL_RGB, GL_UNSIGNED_BYTE, image.GetData());
1901void pi_ocpnDC::DrawText(
const wxString &text, wxCoord x, wxCoord y) {
1902 if (dc) dc->DrawText(text, x, y);
1909 m_texfont.Build(m_font);
1910 m_texfont.GetTextExtent(text, &w, &h);
1914 glEnable(GL_TEXTURE_2D);
1915 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1916 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1920 glTranslatef(x, y, 0);
1922 glColor3ub(m_textforegroundcolour.Red(), m_textforegroundcolour.Green(),
1923 m_textforegroundcolour.Blue());
1925 m_texfont.RenderString(text);
1928 m_texfont.RenderString(text, x, y);
1930 glDisable(GL_TEXTURE_2D);
1931 glDisable(GL_BLEND);
1935 sdc.SetFont(m_font);
1936 sdc.GetMultiLineTextExtent(text, &w, &h,
nullptr,
1939 sdc.GetTextExtent(
"W", &ww, &hw);
1941 w *= OCPN_GetWinDIPScaleFactor();
1942 h *= OCPN_GetWinDIPScaleFactor();
1950 temp_dc.SelectObject(bmp);
1953 temp_dc.SetBackground(wxBrush(wxColour(0, 0, 0)));
1957 temp_dc.SetFont(m_font);
1958 temp_dc.SetTextForeground(wxColour(255, 255, 255));
1959 temp_dc.DrawText(text, 0, 0);
1960 temp_dc.SelectObject(wxNullBitmap);
1964 wxImage image = bmp.ConvertToImage();
1967 int dx = (x < 0 ? -x : 0);
1968 int dy = (y < 0 ? -y : 0);
1969 w = bmp.GetWidth() - dx;
1970 h = bmp.GetHeight() - dy;
1972 if (w <= 0 || h <= 0)
return;
1973 image = image.GetSubImage(wxRect(dx, dy, w, h));
1978 unsigned char *data =
new unsigned char[w * h * 4];
1979 unsigned char *im = image.GetData();
1982 unsigned int r = m_textforegroundcolour.Red();
1983 unsigned int g = m_textforegroundcolour.Green();
1984 unsigned int b = m_textforegroundcolour.Blue();
1985 for (
int i = 0; i < h; i++) {
1986 for (
int j = 0; j < w; j++) {
1987 unsigned int index = ((i * w) + j) * 4;
1989 data[index + 1] = g;
1990 data[index + 2] = b;
1991 data[index + 3] = im[((i * w) + j) * 3];
1996 glColor4ub( 255, 255, 255, 255 );
1997 glEnable( GL_BLEND );
1998 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1999 glRasterPos2i( x, y );
2000 glPixelZoom( 1, -1 );
2001 glDrawPixels( w, h, GL_RGBA, GL_UNSIGNED_BYTE, data );
2002 glPixelZoom( 1, 1 );
2003 glDisable( GL_BLEND );
2005 unsigned int texobj;
2007 glGenTextures(1, &texobj);
2008 glBindTexture(GL_TEXTURE_2D, texobj);
2010 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2011 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2013 int TextureWidth = NextPow2(w);
2014 int TextureHeight = NextPow2(h);
2015 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TextureWidth, TextureHeight, 0,
2016 GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
2017 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
2020 glEnable(GL_TEXTURE_2D);
2022 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2024 float u = (float)w / TextureWidth, v = (
float)h / TextureHeight;
2027 glColor3ub(0, 0, 0);
2033 glVertex2f(x + w, y);
2035 glVertex2f(x + w, y + h);
2037 glVertex2f(x, y + h);
2063 glUseProgram(pi_texture_2D_shader_program);
2067 glGetAttribLocation(pi_texture_2D_shader_program,
"aPos");
2069 glGetAttribLocation(pi_texture_2D_shader_program,
"aUV");
2072 GLint texUni = glGetUniformLocation(pi_texture_2D_shader_program,
"uTex");
2073 glUniform1i(texUni, 0);
2076 glBindBuffer(GL_ARRAY_BUFFER, 0);
2077 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2081 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, coords);
2083 glEnableVertexAttribArray(mPosAttrib);
2086 glVertexAttribPointer(mUvAttrib, 2, GL_FLOAT, GL_FALSE, 0, uv);
2088 glEnableVertexAttribArray(mUvAttrib);
2094 mat4x4_rotate_Z(Q, I, angle);
2101 glGetUniformLocation(pi_texture_2D_shader_program,
"TransformMatrix");
2102 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)Q);
2105 glActiveTexture(GL_TEXTURE0);
2110 GLushort indices1[] = {0,1,3,2};
2111 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, indices1);
2134 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, co1);
2135 glVertexAttribPointer(mUvAttrib, 2, GL_FLOAT, GL_FALSE, 0, tco1);
2137 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2138 glDisableVertexAttribArray(mPosAttrib);
2139 glDisableVertexAttribArray(mUvAttrib);
2146 glDisable(GL_BLEND);
2147 glDisable(GL_TEXTURE_2D);
2149 glDeleteTextures(1, &texobj);
2157void pi_ocpnDC::GetTextExtent(
const wxString &
string, wxCoord *w, wxCoord *h,
2158 wxCoord *descent, wxCoord *externalLeading,
2166 dc->GetMultiLineTextExtent(
string, w, h,
nullptr, font);
2169 if (font) f = *font;
2174 m_texfont.GetTextExtent(
string, w, h);
2177 temp_dc.GetMultiLineTextExtent(
string, w, h,
nullptr, &f);
2178 if (w) (*w) *= OCPN_GetWinDIPScaleFactor();
2179 if (h) (*h) *= OCPN_GetWinDIPScaleFactor();
2183 temp_dc.GetMultiLineTextExtent(
string, w, h,
nullptr, &f);
2184 if (w) (*w) *= OCPN_GetWinDIPScaleFactor();
2185 if (h) (*h) *= OCPN_GetWinDIPScaleFactor();
2191 if (w && (*w > 2000)) *w = 2000;
2192 if (h && (*h > 500)) *h = 500;
2195void pi_ocpnDC::ResetBoundingBox() {
2196 if (dc) dc->ResetBoundingBox();
2199void pi_ocpnDC::CalcBoundingBox(wxCoord x, wxCoord y) {
2200 if (dc) dc->CalcBoundingBox(x, y);
2203bool pi_ocpnDC::ConfigurePen() {
2204 if (!m_pen.IsOk())
return false;
2205 if (m_pen == *wxTRANSPARENT_PEN)
return false;
2207 wxColour c = m_pen.GetColour();
2208 int width = m_pen.GetWidth();
2210 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
2211 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, width));
2216bool pi_ocpnDC::ConfigureBrush() {
2217 if (m_brush == wxNullBrush || m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT)
2220 wxColour c = m_brush.GetColour();
2221 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
2226void pi_ocpnDC::GLDrawBlendData(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
2227 int format,
const unsigned char *data) {
2229#ifndef USE_ANDROID_GLES2
2231 glRasterPos2i(x, y);
2233 glDrawPixels(w, h, format, GL_UNSIGNED_BYTE, data);
2235 glDisable(GL_BLEND);
PlugIn Object Definition/API.
OpenGL Platform Abstraction Layer.