48#include <wx/glcanvas.h>
51#include <wx/graphics.h>
52#include <wx/dcclient.h>
59#ifdef USE_ANDROID_GLES2
67extern float g_piGLMinSymbolLineWidth;
68wxArrayPtrVoid pi_gTesselatorVertices;
70#ifdef USE_ANDROID_GLES2
71extern GLint GRIBpi_color_tri_shader_program;
72extern GLint pi_circle_filled_shader_program;
73extern GLint texture_2D_shader_program;
76int NextPow2(
int size) {
89pi_ocpnDC::pi_ocpnDC(wxGLCanvas &canvas)
96#if wxUSE_GRAPHICS_CONTEXT
99 m_textforegroundcolour = wxColour(0, 0, 0);
103 s_odc_tess_work_buf =
nullptr;
105#ifdef USE_ANDROID_GLES2
106 s_odc_tess_vertex_idx = 0;
107 s_odc_tess_vertex_idx_this = 0;
108 s_odc_tess_buf_len = 0;
110 s_odc_tess_work_buf = (GLfloat *)malloc(100 *
sizeof(GLfloat));
111 s_odc_tess_buf_len = 100;
118pi_ocpnDC::pi_ocpnDC(wxDC &pdc)
122 m_brush(wxNullBrush),
124#if wxUSE_GRAPHICS_CONTEXT
126 auto pmdc =
dynamic_cast<wxMemoryDC *
>(dc);
128 pgc = wxGraphicsContext::Create(*pmdc);
130 auto pcdc =
dynamic_cast<wxClientDC *
>(dc);
131 if (pcdc) pgc = wxGraphicsContext::Create(*pcdc);
134 m_textforegroundcolour = wxColour(0, 0, 0);
139 s_odc_tess_work_buf =
nullptr;
143pi_ocpnDC::pi_ocpnDC()
147 m_brush(wxNullBrush),
149#if wxUSE_GRAPHICS_CONTEXT
152 m_textforegroundcolour = wxColour(0, 0, 0);
157 s_odc_tess_work_buf =
nullptr;
163pi_ocpnDC::~pi_ocpnDC() {
164#if wxUSE_GRAPHICS_CONTEXT
169 free(s_odc_tess_work_buf);
182void pi_ocpnDC::Clear() {
187 wxBrush tmpBrush = m_brush;
189 SetBrush(wxBrush(glcanvas->GetBackgroundColour()));
190 glcanvas->GetSize(&w, &h);
191 DrawRectangle(0, 0, w, h);
197void pi_ocpnDC::SetBackground(
const wxBrush &brush) {
199 dc->SetBackground(brush);
202 glcanvas->SetBackgroundColour(brush.GetColour());
207void pi_ocpnDC::SetPen(
const wxPen &pen) {
209 if (pen == wxNullPen)
210 dc->SetPen(*wxTRANSPARENT_PEN);
217void pi_ocpnDC::SetBrush(
const wxBrush &brush) {
224void pi_ocpnDC::SetTextForeground(
const wxColour &colour) {
226 dc->SetTextForeground(colour);
228 m_textforegroundcolour = colour;
231void pi_ocpnDC::SetFont(
const wxFont &font) {
238const wxPen &pi_ocpnDC::GetPen()
const {
239 if (dc)
return dc->GetPen();
243const wxBrush &pi_ocpnDC::GetBrush()
const {
244 if (dc)
return dc->GetBrush();
248const wxFont &pi_ocpnDC::GetFont()
const {
249 if (dc)
return dc->GetFont();
253void pi_ocpnDC::GetSize(wxCoord *width, wxCoord *height)
const {
255 dc->GetSize(width, height);
258 glcanvas->GetSize(width, height);
263void pi_ocpnDC::SetGLAttrs(
bool highQuality) {
268 glEnable(GL_LINE_SMOOTH);
269 glEnable(GL_POLYGON_SMOOTH);
272 glDisable(GL_LINE_SMOOTH);
273 glDisable(GL_POLYGON_SMOOTH);
279void pi_ocpnDC::SetGLStipple()
const {
282#ifndef USE_ANDROID_GLES2
283 switch (m_pen.GetStyle()) {
284 case wxPENSTYLE_DOT: {
285 glLineStipple(1, 0x3333);
286 glEnable(GL_LINE_STIPPLE);
289 case wxPENSTYLE_LONG_DASH: {
290 glLineStipple(1, 0xFFF8);
291 glEnable(GL_LINE_STIPPLE);
294 case wxPENSTYLE_SHORT_DASH: {
295 glLineStipple(1, 0x3F3F);
296 glEnable(GL_LINE_STIPPLE);
299 case wxPENSTYLE_DOT_DASH: {
300 glLineStipple(1, 0x8FF1);
301 glEnable(GL_LINE_STIPPLE);
313void piDrawEndCap(
float x1,
float y1,
float t1,
float angle) {
314#ifndef USE_ANDROID_GLES2
315 const int steps = 16;
318 for (
int i = 0; i <= steps; i++) {
319 float a = angle + M_PI / 2 + M_PI / steps * i;
321 float xb = x1 + t1 / 2 * cos(a);
322 float yb = y1 + t1 / 2 * sin(a);
337void piDrawGLThickLine(
float x1,
float y1,
float x2,
float y2, wxPen pen,
341 float angle = atan2f(y2 - y1, x2 - x1);
342 float t1 = pen.GetWidth();
343 float t2sina1 = t1 / 2 * sinf(angle);
344 float t2cosa1 = t1 / 2 * cosf(angle);
346#ifndef USE_ANDROID_GLES2
347 glBegin(GL_TRIANGLES);
352 int n_dashes = pen.GetDashes(&dashes);
354 float lpix = sqrtf(powf((
float)(x1 - x2), 2) + powf((
float)(y1 - y2), 2));
358 float ldraw = t1 * dashes[0];
359 float lspace = t1 * dashes[1];
361 while (lrun < lpix) {
363 float xb = xa + ldraw * cosf(angle);
364 float yb = ya + ldraw * sinf(angle);
366 if ((lrun + ldraw) >= lpix)
372 glVertex2f(xa + t2sina1, ya - t2cosa1);
373 glVertex2f(xb + t2sina1, yb - t2cosa1);
374 glVertex2f(xb - t2sina1, yb + t2cosa1);
376 glVertex2f(xb - t2sina1, yb + t2cosa1);
377 glVertex2f(xa - t2sina1, ya + t2cosa1);
378 glVertex2f(xa + t2sina1, ya - t2cosa1);
385 xb = xa + lspace * cos(angle);
386 yb = ya + lspace * sin(angle);
393 glVertex2f(x1 + t2sina1, y1 - t2cosa1);
394 glVertex2f(x2 + t2sina1, y2 - t2cosa1);
395 glVertex2f(x2 - t2sina1, y2 + t2cosa1);
397 glVertex2f(x2 - t2sina1, y2 + t2cosa1);
398 glVertex2f(x1 - t2sina1, y1 + t2cosa1);
399 glVertex2f(x1 + t2sina1, y1 - t2cosa1);
403 if (pen.GetCap() == wxCAP_ROUND) {
404 piDrawEndCap(x1, y1, t1, angle);
405 piDrawEndCap(x2, y2, t1, angle + M_PI);
415 int n_dashes = pen.GetDashes(&dashes);
417 float lpix = sqrtf(powf((
float)(x1 - x2), 2) + powf((
float)(y1 - y2), 2));
421 float ldraw = t1 * dashes[0];
422 float lspace = t1 * dashes[1];
424 glUseProgram(GRIBpi_color_tri_shader_program);
429 glBindBuffer(GL_ARRAY_BUFFER, 0);
430 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
433 glGetAttribLocation(GRIBpi_color_tri_shader_program,
"position");
434 glEnableVertexAttribArray(pos);
435 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float), vert);
441 GLint matloc = glGetUniformLocation(GRIBpi_color_tri_shader_program,
443 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)I);
445 wxColor c = pen.GetColour();
447 colorv[0] = c.Red() / float(256);
448 colorv[1] = c.Green() / float(256);
449 colorv[2] = c.Blue() / float(256);
450 colorv[3] = c.Alpha() / float(256);
453 glGetUniformLocation(GRIBpi_color_tri_shader_program,
"color");
454 glUniform4fv(colloc, 1, colorv);
456 while (lrun < lpix) {
458 float xb = xa + ldraw * cosf(angle);
459 float yb = ya + ldraw * sinf(angle);
461 if ((lrun + ldraw) >= lpix)
467 vert[0] = xa + t2sina1;
468 vert[1] = ya - t2cosa1;
469 vert[2] = xb + t2sina1;
470 vert[3] = yb - t2cosa1;
471 vert[4] = xb - t2sina1;
472 vert[5] = yb + t2cosa1;
473 vert[6] = xb - t2sina1;
474 vert[7] = yb + t2cosa1;
475 vert[8] = xa - t2sina1;
476 vert[9] = ya + t2cosa1;
477 vert[10] = xa + t2sina1;
478 vert[11] = ya - t2cosa1;
480 glDrawArrays(GL_TRIANGLES, 0, 6);
487 xb = xa + lspace * cos(angle);
488 yb = ya + lspace * sin(angle);
496 vert[0] = x1 + t2sina1;
497 vert[1] = y1 - t2cosa1;
498 vert[2] = x2 + t2sina1;
499 vert[3] = y2 - t2cosa1;
500 vert[4] = x2 - t2sina1;
501 vert[5] = y2 + t2cosa1;
502 vert[6] = x2 - t2sina1;
503 vert[7] = y2 + t2cosa1;
504 vert[8] = x1 - t2sina1;
505 vert[9] = y1 + t2cosa1;
506 vert[10] = x1 + t2sina1;
507 vert[11] = y1 - t2cosa1;
509 glUseProgram(GRIBpi_color_tri_shader_program);
512 glBindBuffer(GL_ARRAY_BUFFER, 0);
513 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
516 glGetAttribLocation(GRIBpi_color_tri_shader_program,
"position");
517 glEnableVertexAttribArray(pos);
518 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float), vert);
524 GLint matloc = glGetUniformLocation(GRIBpi_color_tri_shader_program,
526 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)I);
528 wxColor c = pen.GetColour();
530 colorv[0] = c.Red() / float(256);
531 colorv[1] = c.Green() / float(256);
532 colorv[2] = c.Blue() / float(256);
533 colorv[3] = c.Alpha() / float(256);
536 glGetUniformLocation(GRIBpi_color_tri_shader_program,
"color");
537 glUniform4fv(colloc, 1, colorv);
539 glDrawArrays(GL_TRIANGLES, 0, 6);
540 glDisableVertexAttribArray(pos);
557void pi_ocpnDC::DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2,
559 if (dc) dc->DrawLine(x1, y1, x2, y2);
561 else if (ConfigurePen()) {
562 bool b_draw_thick =
false;
564 float pen_width = wxMax(g_piGLMinSymbolLineWidth, m_pen.GetWidth());
572 glEnable(GL_LINE_SMOOTH);
575 if (pen_width > 1.0) {
577 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
578 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
579 if (pen_width > parms[1])
582 glLineWidth(pen_width);
584 glLineWidth(pen_width);
588 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
589 if (pen_width > parms[1])
592 glLineWidth(pen_width);
594 glLineWidth(pen_width);
599 piDrawGLThickLine(x1, y1, x2, y2, m_pen, b_hiqual);
601 glUseProgram(GRIBpi_color_tri_shader_program);
605 glGetAttribLocation(GRIBpi_color_tri_shader_program,
"position");
606 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float),
608 glEnableVertexAttribArray(pos);
616 colorv[0] = m_pen.GetColour().Red() / float(256);
617 colorv[1] = m_pen.GetColour().Green() / float(256);
618 colorv[2] = m_pen.GetColour().Blue() / float(256);
622 glGetUniformLocation(GRIBpi_color_tri_shader_program,
"color");
623 glUniform4fv(colloc, 1, colorv);
626 int n_dashes = m_pen.GetDashes(&dashes);
628 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
629 float cosa = cosf(angle);
630 float sina = sinf(angle);
631 float t1 = m_pen.GetWidth();
633 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
637 float ldraw = t1 * dashes[0];
638 float lspace = t1 * dashes[1];
640 ldraw = wxMax(ldraw, 4.0);
641 lspace = wxMax(lspace, 4.0);
642 lpix = wxMin(lpix, 2000.0);
644 while (lrun < lpix) {
646 float xb = xa + ldraw * cosa;
647 float yb = ya + ldraw * sina;
649 if ((lrun + ldraw) >= lpix)
660 glDrawArrays(GL_LINES, 0, 2);
661 glDisableVertexAttribArray(pos);
663 xa = xa + (lspace + ldraw) * cosa;
664 ya = ya + (lspace + ldraw) * sina;
665 lrun += lspace + ldraw;
674 glDrawArrays(GL_LINES, 0, 2);
675 glDisableVertexAttribArray(pos);
683 piDrawGLThickLine(x1, y1, x2, y2, m_pen, b_hiqual);
686 int n_dashes = m_pen.GetDashes(&dashes);
688 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
689 float cosa = cosf(angle);
690 float sina = sinf(angle);
691 float t1 = m_pen.GetWidth();
693 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
697 float ldraw = t1 * dashes[0];
698 float lspace = t1 * dashes[1];
700 ldraw = wxMax(ldraw, 4.0);
701 lspace = wxMax(lspace, 4.0);
702 lpix = wxMin(lpix, 2000.0);
705 while (lrun < lpix) {
707 float xb = xa + ldraw * cosa;
708 float yb = ya + ldraw * sina;
710 if ((lrun + ldraw) >= lpix)
719 xa = xa + (lspace + ldraw) * cosa;
720 ya = ya + (lspace + ldraw) * sina;
721 lrun += lspace + ldraw;
733 glDisable(GL_LINE_STIPPLE);
736 glDisable(GL_LINE_SMOOTH);
744void piDrawGLThickLines(
int n, wxPoint points[], wxCoord xoffset,
745 wxCoord yoffset, wxPen pen,
bool b_hiqual) {
749#ifdef USE_ANDROID_GLES2
750 wxPoint p0 = points[0];
751 for (
int i = 1; i < n; i++) {
752 piDrawGLThickLine(p0.x + xoffset, p0.y + yoffset, points[i].x + xoffset,
753 points[i].y + yoffset, pen, b_hiqual);
761 if (pen.GetDashes(&dashes)) {
762 wxPoint p0 = points[0];
763 for (
int i = 1; i < n; i++) {
764 piDrawGLThickLine(p0.x + xoffset, p0.y + yoffset, points[i].x + xoffset,
765 points[i].y + yoffset, pen, b_hiqual);
772 wxPoint *cpoints =
new wxPoint[n];
773 cpoints[0] = points[0];
775 for (
int i = 1; i < n; i++) {
776 if (points[i].x != points[i - 1].x || points[i].y != points[i - 1].y)
777 cpoints[c++] = points[i];
784 float t1 = pen.GetWidth();
786 float x0 = cpoints[0].x, y0 = cpoints[0].y, x1 = cpoints[1].x,
788 float a0 = atan2f(y1 - y0, x1 - x0);
792 glBegin(GL_TRIANGLES);
794 float t2sina0 = t1 / 2 * sinf(a0);
795 float t2cosa0 = t1 / 2 * cosf(a0);
797 for (
int i = 1; i < c; i++) {
802 x2 = cpoints[i + 1].x, y2 = cpoints[i + 1].y;
803 a1 = atan2f(y2 - y1, x2 - x1);
809 float aa = (a0 + a1) / 2;
810 float diff = fabsf(a0 - a1);
811 if (diff > M_PI) diff -= 2 * (float)M_PI;
812 float rad = t1 / 2 / wxMax(cosf(diff / 2), .4);
814 float t2sina1 = rad * sinf(aa);
815 float t2cosa1 = rad * cosf(aa);
817 glVertex2f(x1 + t2sina1, y1 - t2cosa1);
818 glVertex2f(x1 - t2sina1, y1 + t2cosa1);
819 glVertex2f(x0 + t2sina0, y0 - t2cosa0);
821 glVertex2f(x0 - t2sina0, y0 + t2cosa0);
822 glVertex2f(x0 + t2sina0, y0 - t2cosa0);
824 float dot = t2sina0 * t2sina1 + t2cosa0 * t2cosa1;
826 glVertex2f(x1 - t2sina1, y1 + t2cosa1);
828 glVertex2f(x1 + t2sina1, y1 - t2cosa1);
833 t2sina0 = t2sina1, t2cosa0 = t2cosa1;
836 if (pen.GetCap() == wxCAP_ROUND) {
837 piDrawEndCap(x0, y0, t1, a0);
838 piDrawEndCap(x0, y0, t1, a0 + M_PI);
850void pi_ocpnDC::DrawLines(
int n, wxPoint points[], wxCoord xoffset,
851 wxCoord yoffset,
bool b_hiqual) {
852 if (dc) dc->DrawLines(n, points, xoffset, yoffset);
854 else if (ConfigurePen()) {
859 SetGLAttrs(b_hiqual);
861 bool b_draw_thick =
false;
863 glDisable(GL_LINE_STIPPLE);
869 if (m_pen.GetWidth() > 1) {
871 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
872 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
874 if (m_pen.GetWidth() > parms[1])
877 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, m_pen.GetWidth()));
879 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, 1));
881 if (m_pen.GetWidth() > 1) {
883 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
884 if (m_pen.GetWidth() > parms[1])
887 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, m_pen.GetWidth()));
889 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, 1));
893 piDrawGLThickLines(n, points, xoffset, yoffset, m_pen, b_hiqual);
896 glDisable(GL_LINE_STIPPLE);
897 glDisable(GL_POLYGON_SMOOTH);
906 glBegin(GL_LINE_STRIP);
907 for (
int i = 0; i < n; i++)
908 glVertex2i(points[i].x + xoffset, points[i].y + yoffset);
914 if (workBufSize < (
size_t)n * 2) {
915 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
919 for (
int i = 0; i < n; i++) {
920 workBuf[i * 2] = points[i].x + xoffset;
921 workBuf[(i * 2) + 1] = points[i].y + yoffset;
924 glUseProgram(GRIBpi_color_tri_shader_program);
927 glGetAttribLocation(GRIBpi_color_tri_shader_program,
"position");
928 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float),
930 glEnableVertexAttribArray(pos);
937 colorv[0] = m_pen.GetColour().Red() / float(256);
938 colorv[1] = m_pen.GetColour().Green() / float(256);
939 colorv[2] = m_pen.GetColour().Blue() / float(256);
940 colorv[3] = m_pen.GetColour().Alpha() / float(256);
944 glGetUniformLocation(GRIBpi_color_tri_shader_program,
"color");
945 glUniform4fv(colloc, 1, colorv);
947 glDrawArrays(GL_LINE_STRIP, 0, n);
948 glDisableVertexAttribArray(pos);
955 glDisable(GL_LINE_STIPPLE);
956 glDisable(GL_POLYGON_SMOOTH);
963void pi_ocpnDC::StrokeLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) {
964#if wxUSE_GRAPHICS_CONTEXT
966 pgc->SetPen(dc->GetPen());
967 pgc->StrokeLine(x1, y1, x2, y2);
969 dc->CalcBoundingBox(x1, y1);
970 dc->CalcBoundingBox(x2, y2);
973 DrawLine(x1, y1, x2, y2,
true);
976void pi_ocpnDC::StrokeLines(
int n, wxPoint *points) {
980#if wxUSE_GRAPHICS_CONTEXT
982 wxPoint2DDouble *dPoints =
983 (wxPoint2DDouble *)malloc(n *
sizeof(wxPoint2DDouble));
984 for (
int i = 0; i < n; i++) {
985 dPoints[i].m_x = points[i].x;
986 dPoints[i].m_y = points[i].y;
988 pgc->SetPen(dc->GetPen());
989 pgc->StrokeLines(n, dPoints);
993 DrawLines(n, points, 0, 0,
true);
996void pi_ocpnDC::DrawGLLineArray(
int n,
float *vertex_array,
float *color_array,
997 unsigned char *color_array_ub,
bool b_hiqual) {
1001 if (ConfigurePen()) {
1006 SetGLAttrs(b_hiqual);
1008 bool b_draw_thick =
false;
1010 glDisable(GL_LINE_STIPPLE);
1016 if (m_pen.GetWidth() > 1) {
1022 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, m_pen.GetWidth()));
1024 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, 1));
1026 if (m_pen.GetWidth() > 1) {
1029 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, m_pen.GetWidth()));
1031 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, 1));
1036 glEnableClientState(GL_VERTEX_ARRAY);
1037 glEnableClientState(GL_COLOR_ARRAY);
1039 glColorPointer(4, GL_UNSIGNED_BYTE, 4 *
sizeof(
unsigned char),
1041 glVertexPointer(2, GL_FLOAT, 2 *
sizeof(
float), vertex_array);
1042 glDrawArrays(GL_LINES, 0, n);
1044 glDisableClientState(GL_VERTEX_ARRAY);
1045 glDisableClientState(GL_COLOR_ARRAY);
1054 glUseProgram(GRIBpi_colorv_tri_shader_program);
1057 glGetAttribLocation(GRIBpi_colorv_tri_shader_program,
"position");
1058 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float),
1060 glEnableVertexAttribArray(pos);
1063 glGetAttribLocation(GRIBpi_colorv_tri_shader_program,
"colorv");
1064 glVertexAttribPointer(colloc, 4, GL_FLOAT, GL_FALSE, 4 *
sizeof(
float),
1066 glEnableVertexAttribArray(colloc);
1068 glDrawArrays(GL_LINES, 0, n);
1069 glDisableVertexAttribArray(pos);
1070 glDisableVertexAttribArray(colloc);
1077 glDisable(GL_LINE_STIPPLE);
1078 glDisable(GL_POLYGON_SMOOTH);
1079 glDisable(GL_BLEND);
1085void pi_ocpnDC::DrawRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h) {
1086 if (dc) dc->DrawRectangle(x, y, w, h);
1090 if (ConfigureBrush()) {
1093 glVertex2i(x + w, y);
1094 glVertex2i(x + w, y + h);
1095 glVertex2i(x, y + h);
1099 if (ConfigurePen()) {
1100 glBegin(GL_LINE_LOOP);
1102 glVertex2i(x + w, y);
1103 glVertex2i(x + w, y + h);
1104 glVertex2i(x, y + h);
1108 DrawRoundedRectangle(x, y, w, h, 0);
1116static void drawrrhelper(wxCoord x0, wxCoord y0, wxCoord r,
int quadrant,
1119#ifndef USE_ANDROID_GLES2
1120 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
1124 x = r, y = 0, dx = 0, dy = -rs, ddx = -rss, ddy = rss;
1127 x = 0, y = -r, dx = -rs, dy = 0, ddx = rss, ddy = rss;
1130 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
1133 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
1139 for (
int i = 0; i < steps; i++) {
1140 glVertex2i(x0 + floor(x), y0 + floor(y));
1141 x += dx + ddx / 2, y += dy + ddy / 2;
1142 dx += ddx, dy += ddy;
1144 glVertex2i(x0 + floor(x), y0 + floor(y));
1149void pi_ocpnDC::drawrrhelperGLES2(wxCoord x0, wxCoord y0, wxCoord r,
1150 int quadrant,
int steps) {
1152 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
1156 x = r, y = 0, dx = 0, dy = -rs, ddx = -rss, ddy = rss;
1159 x = 0, y = -r, dx = -rs, dy = 0, ddx = rss, ddy = rss;
1162 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
1165 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
1171 for (
int i = 0; i < steps; i++) {
1172 workBuf[workBufIndex++] = x0 + floor(x);
1173 workBuf[workBufIndex++] = y0 + floor(y);
1175 x += dx + ddx / 2, y += dy + ddy / 2;
1176 dx += ddx, dy += ddy;
1179 workBuf[workBufIndex++] = x0 + floor(x);
1180 workBuf[workBufIndex++] = y0 + floor(y);
1184void pi_ocpnDC::DrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
1186 if (dc) dc->DrawRoundedRectangle(x, y, w, h, r);
1190 int steps = ceil(sqrt((
float)r));
1192 wxCoord x1 = x + r, x2 = x + w - r;
1193 wxCoord y1 = y + r, y2 = y + h - r;
1198 size_t bufReq = steps * 8 * 2 *
sizeof(float);
1200 if (workBufSize < bufReq) {
1201 workBuf = (
float *)realloc(workBuf, bufReq);
1202 workBufSize = bufReq;
1206 drawrrhelperGLES2(x2, y1, r, 0, steps);
1207 drawrrhelperGLES2(x1, y1, r, 1, steps);
1208 drawrrhelperGLES2(x1, y2, r, 2, steps);
1209 drawrrhelperGLES2(x2, y2, r, 3, steps);
1211 glUseProgram(GRIBpi_color_tri_shader_program);
1215 glGetAttribLocation(GRIBpi_color_tri_shader_program,
"position");
1218 glBindBuffer(GL_ARRAY_BUFFER, 0);
1219 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1221 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, workBuf);
1222 glEnableVertexAttribArray(mPosAttrib);
1226 bcolorv[0] = m_brush.GetColour().Red() / float(256);
1227 bcolorv[1] = m_brush.GetColour().Green() / float(256);
1228 bcolorv[2] = m_brush.GetColour().Blue() / float(256);
1229 bcolorv[3] = m_brush.GetColour().Alpha() / float(256);
1232 glGetUniformLocation(GRIBpi_color_tri_shader_program,
"color");
1233 glUniform4fv(bcolloc, 1, bcolorv);
1242 mat4x4_rotate_Z(Q, I, angle);
1248 GLint matloc = glGetUniformLocation(GRIBpi_color_tri_shader_program,
1250 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)Q);
1253 glDrawArrays(GL_TRIANGLE_FAN, 0, workBufIndex / 2);
1254 glDisableVertexAttribArray(mPosAttrib);
1258 mat4x4_identity(IM);
1259 GLint matlocf = glGetUniformLocation(GRIBpi_color_tri_shader_program,
1261 glUniformMatrix4fv(matlocf, 1, GL_FALSE, (
const GLfloat *)IM);
1265 if (ConfigureBrush()) {
1266 glBegin(GL_TRIANGLE_FAN);
1267 drawrrhelper(x2, y1, r, 0, steps);
1268 drawrrhelper(x1, y1, r, 1, steps);
1269 drawrrhelper(x1, y2, r, 2, steps);
1270 drawrrhelper(x2, y2, r, 3, steps);
1274 if (ConfigurePen()) {
1275 glBegin(GL_LINE_LOOP);
1276 drawrrhelper(x2, y1, r, 0, steps);
1277 drawrrhelper(x1, y1, r, 1, steps);
1278 drawrrhelper(x1, y2, r, 2, steps);
1279 drawrrhelper(x2, y2, r, 3, steps);
1287void pi_ocpnDC::DrawCircle(wxCoord x, wxCoord y, wxCoord radius) {
1288#ifdef USE_ANDROID_GLES2
1294 coords[0] = x - radius;
1295 coords[1] = y + radius;
1296 coords[2] = x + radius;
1297 coords[3] = y + radius;
1298 coords[4] = x - radius;
1299 coords[5] = y - radius;
1300 coords[6] = x + radius;
1301 coords[7] = y - radius;
1303 glUseProgram(pi_circle_filled_shader_program);
1307 glGetAttribLocation(pi_circle_filled_shader_program,
"aPos");
1310 glBindBuffer(GL_ARRAY_BUFFER, 0);
1311 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1313 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, coords);
1314 glEnableVertexAttribArray(mPosAttrib);
1318 glGetUniformLocation(pi_circle_filled_shader_program,
"circle_radius");
1319 glUniform1f(radiusloc, radius);
1323 glGetUniformLocation(pi_circle_filled_shader_program,
"circle_center");
1326 ctrv[1] = m_vpSize.y - y;
1327 glUniform2fv(centerloc, 1, ctrv);
1331 colorv[0] = m_brush.GetColour().Red() / float(256);
1332 colorv[1] = m_brush.GetColour().Green() / float(256);
1333 colorv[2] = m_brush.GetColour().Blue() / float(256);
1334 colorv[3] = (m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT) ? 0.0 : 1.0;
1337 glGetUniformLocation(pi_circle_filled_shader_program,
"circle_color");
1338 glUniform4fv(colloc, 1, colorv);
1342 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1343 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1344 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1345 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1348 glGetUniformLocation(pi_circle_filled_shader_program,
"border_color");
1349 glUniform4fv(bcolloc, 1, bcolorv);
1352 GLint borderWidthloc =
1353 glGetUniformLocation(pi_circle_filled_shader_program,
"border_width");
1354 glUniform1f(borderWidthloc, m_pen.GetWidth());
1362 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1363 glDisableVertexAttribArray(mPosAttrib);
1366 glDisable(GL_BLEND);
1369 DrawEllipse(x - radius, y - radius, 2 * radius, 2 * radius);
1373void pi_ocpnDC::StrokeCircle(wxCoord x, wxCoord y, wxCoord radius) {
1374#if wxUSE_GRAPHICS_CONTEXT
1376 wxGraphicsPath gpath = pgc->CreatePath();
1377 gpath.AddCircle(x, y, radius);
1379 pgc->SetPen(GetPen());
1380 pgc->SetBrush(GetBrush());
1381 pgc->DrawPath(gpath);
1384 dc->CalcBoundingBox(x + radius + 2, y + radius + 2);
1385 dc->CalcBoundingBox(x - radius - 2, y - radius - 2);
1388 DrawCircle(x, y, radius);
1391void pi_ocpnDC::DrawEllipse(wxCoord x, wxCoord y, wxCoord width,
1393 if (dc) dc->DrawEllipse(x, y, width, height);
1396 float r1 = width / 2, r2 = height / 2;
1397 float cx = x + r1, cy = y + r2;
1403 float steps = floorf(
1404 wxMax(sqrtf(sqrtf((
float)(width * width + height * height))), 1) *
1407#ifndef USE_ANDROID_GLES2
1408 if (ConfigureBrush()) {
1409 glBegin(GL_TRIANGLE_FAN);
1411 for (
float a = 0; a <= 2 * M_PI + M_PI / steps; a += 2 * M_PI / steps)
1412 glVertex2f(cx + r1 * sinf(a), cy + r2 * cosf(a));
1416 if (ConfigurePen()) {
1417 glBegin(GL_LINE_LOOP);
1418 for (
float a = 0; a < 2 * M_PI - M_PI / steps; a += 2 * M_PI / steps)
1419 glVertex2f(cx + r1 * sinf(a), cy + r2 * cosf(a));
1424 glDisable(GL_BLEND);
1429void pi_ocpnDC::DrawPolygon(
int n, wxPoint points[], wxCoord xoffset,
1430 wxCoord yoffset,
float scale,
float angle) {
1431 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1441#ifdef USE_ANDROID_GLES2
1446 DrawPolygonTessellated(n, points, xoffset, yoffset);
1450 if (workBufSize < (
size_t)n * 2) {
1451 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
1452 workBufSize = n * 4;
1455 for (
int i = 0; i < n; i++) {
1456 workBuf[i * 2] = (points[i].x *
scale);
1457 workBuf[i * 2 + 1] = (points[i].y *
scale);
1460 glUseProgram(GRIBpi_color_tri_shader_program);
1464 glGetAttribLocation(GRIBpi_color_tri_shader_program,
"position");
1467 glBindBuffer(GL_ARRAY_BUFFER, 0);
1468 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1470 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, workBuf);
1471 glEnableVertexAttribArray(mPosAttrib);
1475 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1476 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1477 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1478 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1481 glGetUniformLocation(GRIBpi_color_tri_shader_program,
"color");
1482 glUniform4fv(bcolloc, 1, bcolorv);
1487 mat4x4_rotate_Z(Q, I, angle);
1493 GLint matloc = glGetUniformLocation(GRIBpi_color_tri_shader_program,
1495 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)Q);
1498 glDrawArrays(GL_LINE_LOOP, 0, n);
1501 bcolorv[0] = m_brush.GetColour().Red() / float(256);
1502 bcolorv[1] = m_brush.GetColour().Green() / float(256);
1503 bcolorv[2] = m_brush.GetColour().Blue() / float(256);
1504 bcolorv[3] = m_brush.GetColour().Alpha() / float(256);
1506 glUniform4fv(bcolloc, 1, bcolorv);
1511 float x1 = workBuf[4];
1512 float y1 = workBuf[5];
1513 workBuf[4] = workBuf[6];
1514 workBuf[5] = workBuf[7];
1518 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1519 }
else if (n == 3) {
1520 glDrawArrays(GL_TRIANGLES, 0, 3);
1523 glDisableVertexAttribArray(mPosAttrib);
1527 mat4x4_identity(IM);
1528 GLint matlocf = glGetUniformLocation(GRIBpi_color_tri_shader_program,
1530 glUniformMatrix4fv(matlocf, 1, GL_FALSE, (
const GLfloat *)IM);
1537 if (ConfigureBrush()) {
1538 glEnable(GL_POLYGON_SMOOTH);
1539 glBegin(GL_POLYGON);
1540 for (
int i = 0; i < n; i++)
1541 glVertex2f((points[i].x *
scale) + xoffset,
1542 (points[i].y *
scale) + yoffset);
1544 glDisable(GL_POLYGON_SMOOTH);
1547 if (ConfigurePen()) {
1548 glEnable(GL_LINE_SMOOTH);
1549 glBegin(GL_LINE_LOOP);
1550 for (
int i = 0; i < n; i++)
1551 glVertex2f((points[i].x *
scale) + xoffset,
1552 (points[i].y *
scale) + yoffset);
1554 glDisable(GL_LINE_SMOOTH);
1580void APIENTRY pi_ocpnDCcombineCallback(GLdouble coords[3],
1581 GLdouble *vertex_data[4],
1582 GLfloat weight[4], GLdouble **dataOut) {
1585 vertex =
new GLvertex();
1586 pi_gTesselatorVertices.Add(vertex);
1588 vertex->info.x = coords[0];
1589 vertex->info.y = coords[1];
1590 vertex->info.z = coords[2];
1592 for (
int i = 3; i < 6; i++) {
1594 weight[0] * vertex_data[0][i] + weight[1] * vertex_data[1][i];
1597 *dataOut = &(vertex->data[0]);
1600void APIENTRY ocpnDCvertexCallback(GLvoid *arg) {
1602 vertex = (GLvertex *)arg;
1603 glVertex2f((
float)vertex->info.x, (
float)vertex->info.y);
1606void APIENTRY ocpnDCerrorCallback(GLenum errorCode) {
1607 const GLubyte *estring;
1608 estring = gluErrorString(errorCode);
1612void APIENTRY ocpnDCbeginCallback(GLenum type) { glBegin(type); }
1614void APIENTRY ocpnDCendCallback() { glEnd(); }
1621static std::list<double *> odc_combine_work_data;
1622static void pi_odc_combineCallbackD(GLdouble coords[3],
1623 GLdouble *vertex_data[4], GLfloat weight[4],
1624 GLdouble **dataOut,
void *data) {
1631void pi_odc_vertexCallbackD_GLSL(GLvoid *vertex,
void *data) {
1635 if (pDC->s_odc_tess_vertex_idx > pDC->s_odc_tess_buf_len - 8) {
1636 int new_buf_len = pDC->s_odc_tess_buf_len + 100;
1637 GLfloat *tmp = pDC->s_odc_tess_work_buf;
1639 pDC->s_odc_tess_work_buf = (GLfloat *)realloc(
1640 pDC->s_odc_tess_work_buf, new_buf_len *
sizeof(GLfloat));
1641 if (
nullptr == pDC->s_odc_tess_work_buf) {
1645 pDC->s_odc_tess_buf_len = new_buf_len;
1648 GLdouble *pointer = (GLdouble *)vertex;
1650 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[0];
1651 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[1];
1653 pDC->s_odc_nvertex++;
1656void pi_odc_beginCallbackD_GLSL(GLenum mode,
void *data) {
1658 pDC->s_odc_tess_vertex_idx_this = pDC->s_odc_tess_vertex_idx;
1659 pDC->s_odc_tess_mode = mode;
1660 pDC->s_odc_nvertex = 0;
1663void pi_odc_endCallbackD_GLSL(
void *data) {
1669 glUseProgram(GRIBpi_color_tri_shader_program);
1672 glBindBuffer(GL_ARRAY_BUFFER, 0);
1673 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1675 float *bufPt = &(pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx_this]);
1676 GLint pos = glGetAttribLocation(GRIBpi_color_tri_shader_program,
"position");
1677 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float), bufPt);
1678 glEnableVertexAttribArray(pos);
1686 wxColour c = pDC->GetBrush().GetColour();
1688 colorv[0] = c.Red() / float(256);
1689 colorv[1] = c.Green() / float(256);
1690 colorv[2] = c.Blue() / float(256);
1691 colorv[3] = c.Alpha() / float(256);
1693 GLint colloc = glGetUniformLocation(GRIBpi_color_tri_shader_program,
"color");
1694 glUniform4fv(colloc, 1, colorv);
1696 glDrawArrays(pDC->s_odc_tess_mode, 0, pDC->s_odc_nvertex);
1698 glDisableVertexAttribArray(pos);
1707void pi_ocpnDC::DrawPolygonTessellated(
int n, wxPoint points[], wxCoord xoffset,
1709 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1712#if !defined(ocpnUSE_GLES) || \
1713 defined(USE_ANDROID_GLES2)
1717 DrawPolygon(n, points, xoffset, yoffset);
1722 m_tobj = gluNewTess();
1723 s_odc_tess_vertex_idx = 0;
1725 gluTessCallback(m_tobj, GLU_TESS_VERTEX_DATA,
1726 (_GLUfuncptr)&pi_odc_vertexCallbackD_GLSL);
1727 gluTessCallback(m_tobj, GLU_TESS_BEGIN_DATA,
1728 (_GLUfuncptr)&pi_odc_beginCallbackD_GLSL);
1729 gluTessCallback(m_tobj, GLU_TESS_END_DATA,
1730 (_GLUfuncptr)&pi_odc_endCallbackD_GLSL);
1731 gluTessCallback(m_tobj, GLU_TESS_COMBINE_DATA,
1732 (_GLUfuncptr)&pi_odc_combineCallbackD);
1735 gluTessNormal(m_tobj, 0, 0, 1);
1736 gluTessProperty(m_tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
1738 if (ConfigureBrush()) {
1739 gluTessBeginPolygon(m_tobj,
this);
1740 gluTessBeginContour(m_tobj);
1742 for (
int i = 0; i < n; i++) {
1743 double *p =
new double[6];
1744 p[0] = points[i].x, p[1] = points[i].y, p[2] = 0;
1745 gluTessVertex(m_tobj, p, p);
1748 gluTessEndContour(m_tobj);
1749 gluTessEndPolygon(m_tobj);
1752 gluDeleteTess(m_tobj);
1761 static GLUtesselator *tobj =
nullptr;
1762 if (!tobj) tobj = gluNewTess();
1764 gluTessCallback(tobj, GLU_TESS_VERTEX, (_GLUfuncptr)&ocpnDCvertexCallback);
1765 gluTessCallback(tobj, GLU_TESS_BEGIN, (_GLUfuncptr)&ocpnDCbeginCallback);
1766 gluTessCallback(tobj, GLU_TESS_END, (_GLUfuncptr)&ocpnDCendCallback);
1767 gluTessCallback(tobj, GLU_TESS_COMBINE,
1768 (_GLUfuncptr)&pi_ocpnDCcombineCallback);
1769 gluTessCallback(tobj, GLU_TESS_ERROR, (_GLUfuncptr)&ocpnDCerrorCallback);
1771 gluTessNormal(tobj, 0, 0, 1);
1772 gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
1774 if (ConfigureBrush()) {
1775 gluTessBeginPolygon(tobj,
nullptr);
1776 gluTessBeginContour(tobj);
1778 for (
int i = 0; i < n; i++) {
1779 GLvertex *vertex =
new GLvertex();
1780 pi_gTesselatorVertices.Add(vertex);
1781 vertex->info.x = (GLdouble)points[i].x;
1782 vertex->info.y = (GLdouble)points[i].y;
1783 vertex->info.z = (GLdouble)0.0;
1784 vertex->info.r = (GLdouble)0.0;
1785 vertex->info.g = (GLdouble)0.0;
1786 vertex->info.b = (GLdouble)0.0;
1787 gluTessVertex(tobj, (GLdouble *)vertex, (GLdouble *)vertex);
1789 gluTessEndContour(tobj);
1790 gluTessEndPolygon(tobj);
1793 for (
unsigned int i = 0; i < pi_gTesselatorVertices.Count(); i++)
1794 delete (GLvertex *)pi_gTesselatorVertices.Item(i);
1795 pi_gTesselatorVertices.Clear();
1797 gluDeleteTess(tobj);
1803void pi_ocpnDC::StrokePolygon(
int n, wxPoint points[], wxCoord xoffset,
1804 wxCoord yoffset,
float scale) {
1805#if wxUSE_GRAPHICS_CONTEXT
1807 wxGraphicsPath gpath = pgc->CreatePath();
1808 gpath.MoveToPoint(points[0].x + xoffset, points[0].y + yoffset);
1809 for (
int i = 1; i < n; i++)
1810 gpath.AddLineToPoint(points[i].x + xoffset, points[i].y + yoffset);
1811 gpath.AddLineToPoint(points[0].x + xoffset, points[0].y + yoffset);
1813 pgc->SetPen(GetPen());
1814 pgc->SetBrush(GetBrush());
1815 pgc->DrawPath(gpath);
1817 for (
int i = 0; i < n; i++)
1818 dc->CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset);
1821 DrawPolygon(n, points, xoffset, yoffset,
scale);
1824void pi_ocpnDC::DrawBitmap(
const wxBitmap &bitmap, wxCoord x, wxCoord y,
1827 if (x < 0 || y < 0) {
1828 int dx = (x < 0 ? -x : 0);
1829 int dy = (y < 0 ? -y : 0);
1830 int w = bitmap.GetWidth() - dx;
1831 int h = bitmap.GetHeight() - dy;
1833 if (w <= 0 || h <= 0)
return;
1834 wxBitmap newBitmap = bitmap.GetSubBitmap(wxRect(dx, dy, w, h));
1841 if (dc) dc->DrawBitmap(bmp, x, y, usemask);
1849#ifndef USE_ANDROID_GLES2
1850 wxImage image = bmp.ConvertToImage();
1851 int w = image.GetWidth(), h = image.GetHeight();
1854 unsigned char *d = image.GetData();
1855 unsigned char *a = image.GetAlpha();
1857 unsigned char mr, mg, mb;
1858 if (!image.GetOrFindMaskColour(&mr, &mg, &mb) && !a) {
1859 printf(
"trying to use mask to draw a bitmap without alpha or mask\n");
1863 if (image.HasMask()) a = 0;
1866 unsigned char *e =
new unsigned char[4 * w * h];
1868 for (
int y = 0; y < h; y++)
1869 for (
int x = 0; x < w; x++) {
1870 unsigned char r, g, b;
1871 int off = (y * image.GetWidth() + x);
1881 a ? a[off] : ((r == mr) && (g == mg) && (b == mb) ? 0 : 255);
1887 glColor4f(1, 1, 1, 1);
1888 GLDrawBlendData(x, y, w, h, GL_RGBA, e);
1891 glRasterPos2i(x, y);
1893 if (image.GetData())
1894 glDrawPixels(w, h, GL_RGB, GL_UNSIGNED_BYTE, image.GetData());
1903void pi_ocpnDC::DrawText(
const wxString &text, wxCoord x, wxCoord y) {
1904 if (dc) dc->DrawText(text, x, y);
1911 m_texfont.Build(m_font);
1912 m_texfont.GetTextExtent(text, &w, &h);
1916 glEnable(GL_TEXTURE_2D);
1917 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1918 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1922 glTranslatef(x, y, 0);
1924 glColor3ub(m_textforegroundcolour.Red(), m_textforegroundcolour.Green(),
1925 m_textforegroundcolour.Blue());
1927 m_texfont.RenderString(text);
1930 m_texfont.RenderString(text, x, y);
1932 glDisable(GL_TEXTURE_2D);
1933 glDisable(GL_BLEND);
1937 sdc.SetFont(m_font);
1938 sdc.GetMultiLineTextExtent(text, &w, &h,
nullptr,
1941 sdc.GetTextExtent(
"W", &ww, &hw);
1952 temp_dc.SelectObject(bmp);
1955 temp_dc.SetBackground(wxBrush(wxColour(0, 0, 0)));
1959 temp_dc.SetFont(m_font);
1960 temp_dc.SetTextForeground(wxColour(255, 255, 255));
1961 temp_dc.DrawText(text, 0, 0);
1962 temp_dc.SelectObject(wxNullBitmap);
1966 wxImage image = bmp.ConvertToImage();
1969 int dx = (x < 0 ? -x : 0);
1970 int dy = (y < 0 ? -y : 0);
1971 w = bmp.GetWidth() - dx;
1972 h = bmp.GetHeight() - dy;
1974 if (w <= 0 || h <= 0)
return;
1975 image = image.GetSubImage(wxRect(dx, dy, w, h));
1980 unsigned char *data =
new unsigned char[w * h * 4];
1981 unsigned char *im = image.GetData();
1984 unsigned int r = m_textforegroundcolour.Red();
1985 unsigned int g = m_textforegroundcolour.Green();
1986 unsigned int b = m_textforegroundcolour.Blue();
1987 for (
int i = 0; i < h; i++) {
1988 for (
int j = 0; j < w; j++) {
1989 unsigned int index = ((i * w) + j) * 4;
1991 data[index + 1] = g;
1992 data[index + 2] = b;
1993 data[index + 3] = im[((i * w) + j) * 3];
1998 glColor4ub( 255, 255, 255, 255 );
1999 glEnable( GL_BLEND );
2000 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
2001 glRasterPos2i( x, y );
2002 glPixelZoom( 1, -1 );
2003 glDrawPixels( w, h, GL_RGBA, GL_UNSIGNED_BYTE, data );
2004 glPixelZoom( 1, 1 );
2005 glDisable( GL_BLEND );
2007 unsigned int texobj;
2009 glGenTextures(1, &texobj);
2010 glBindTexture(GL_TEXTURE_2D, texobj);
2012 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2013 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2015 int TextureWidth = NextPow2(w);
2016 int TextureHeight = NextPow2(h);
2017 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TextureWidth, TextureHeight, 0,
2018 GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
2019 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
2022 glEnable(GL_TEXTURE_2D);
2024 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2026 float u = (float)w / TextureWidth, v = (
float)h / TextureHeight;
2029 glColor3ub(0, 0, 0);
2035 glVertex2f(x + w, y);
2037 glVertex2f(x + w, y + h);
2039 glVertex2f(x, y + h);
2065 glUseProgram(pi_texture_2D_shader_program);
2069 glGetAttribLocation(pi_texture_2D_shader_program,
"aPos");
2071 glGetAttribLocation(pi_texture_2D_shader_program,
"aUV");
2074 GLint texUni = glGetUniformLocation(pi_texture_2D_shader_program,
"uTex");
2075 glUniform1i(texUni, 0);
2078 glBindBuffer(GL_ARRAY_BUFFER, 0);
2079 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2083 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, coords);
2085 glEnableVertexAttribArray(mPosAttrib);
2088 glVertexAttribPointer(mUvAttrib, 2, GL_FLOAT, GL_FALSE, 0, uv);
2090 glEnableVertexAttribArray(mUvAttrib);
2096 mat4x4_rotate_Z(Q, I, angle);
2103 glGetUniformLocation(pi_texture_2D_shader_program,
"TransformMatrix");
2104 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)Q);
2107 glActiveTexture(GL_TEXTURE0);
2112 GLushort indices1[] = {0,1,3,2};
2113 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, indices1);
2136 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, co1);
2137 glVertexAttribPointer(mUvAttrib, 2, GL_FLOAT, GL_FALSE, 0, tco1);
2139 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2140 glDisableVertexAttribArray(mPosAttrib);
2141 glDisableVertexAttribArray(mUvAttrib);
2148 glDisable(GL_BLEND);
2149 glDisable(GL_TEXTURE_2D);
2151 glDeleteTextures(1, &texobj);
2159void pi_ocpnDC::GetTextExtent(
const wxString &
string, wxCoord *w, wxCoord *h,
2160 wxCoord *descent, wxCoord *externalLeading,
2168 dc->GetMultiLineTextExtent(
string, w, h,
nullptr, font);
2171 if (font) f = *font;
2176 m_texfont.GetTextExtent(
string, w, h);
2179 temp_dc.GetMultiLineTextExtent(
string, w, h,
nullptr, &f);
2185 temp_dc.GetMultiLineTextExtent(
string, w, h,
nullptr, &f);
2193 if (w && (*w > 2000)) *w = 2000;
2194 if (h && (*h > 500)) *h = 500;
2197void pi_ocpnDC::ResetBoundingBox() {
2198 if (dc) dc->ResetBoundingBox();
2201void pi_ocpnDC::CalcBoundingBox(wxCoord x, wxCoord y) {
2202 if (dc) dc->CalcBoundingBox(x, y);
2205bool pi_ocpnDC::ConfigurePen() {
2206 if (!m_pen.IsOk())
return false;
2207 if (m_pen == *wxTRANSPARENT_PEN)
return false;
2209 wxColour c = m_pen.GetColour();
2210 int width = m_pen.GetWidth();
2212 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
2213 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, width));
2218bool pi_ocpnDC::ConfigureBrush() {
2219 if (m_brush == wxNullBrush || m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT)
2222 wxColour c = m_brush.GetColour();
2223 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
2228void pi_ocpnDC::GLDrawBlendData(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
2229 int format,
const unsigned char *data) {
2231#ifndef USE_ANDROID_GLES2
2233 glRasterPos2i(x, y);
2235 glDrawPixels(w, h, format, GL_UNSIGNED_BYTE, data);
2237 glDisable(GL_BLEND);
Contains view parameters and status information for a chart display viewport.
int pix_width
Viewport width in pixels.
int pix_height
Viewport height in pixels.
PlugIn Object Definition/API.
double OCPN_GetWinDIPScaleFactor()
Gets Windows-specific DPI scaling factor.
OpenGL Platform Abstraction Layer.
Graphics abstraction layer on top of wxDC or OpenGL.