42#include <wx/glcanvas.h>
45#include <wx/graphics.h>
46#include <wx/dcclient.h>
50#include "GL/gl_private.h"
56#ifdef USE_ANDROID_GLES2
57#include "pi_shaders.h"
64extern float g_piGLMinSymbolLineWidth;
65wxArrayPtrVoid pi_gTesselatorVertices;
67#ifdef USE_ANDROID_GLES2
68extern GLint pi_color_tri_shader_program;
69extern GLint pi_circle_filled_shader_program;
72int NextPow2(
int size) {
85pi_ocpnDC::pi_ocpnDC(wxGLCanvas &canvas)
86 : glcanvas(&canvas), dc(NULL), m_pen(wxNullPen), m_brush(wxNullBrush) {
87#if wxUSE_GRAPHICS_CONTEXT
91 m_textforegroundcolour = wxColour(0, 0, 0);
96 s_odc_tess_work_buf = NULL;
98#ifdef USE_ANDROID_GLES2
99 s_odc_tess_vertex_idx = 0;
100 s_odc_tess_vertex_idx_this = 0;
101 s_odc_tess_buf_len = 0;
103 s_odc_tess_work_buf = (GLfloat *)malloc(100 *
sizeof(GLfloat));
104 s_odc_tess_buf_len = 100;
111pi_ocpnDC::pi_ocpnDC(wxDC &pdc)
112 : glcanvas(NULL), dc(&pdc), m_pen(wxNullPen), m_brush(wxNullBrush) {
113#if wxUSE_GRAPHICS_CONTEXT
115 auto pmdc =
dynamic_cast<wxMemoryDC *
>(dc);
117 pgc = wxGraphicsContext::Create(*pmdc);
119 auto pcdc =
dynamic_cast<wxClientDC *
>(dc);
120 if (pcdc) pgc = wxGraphicsContext::Create(*pcdc);
123 m_textforegroundcolour = wxColour(0, 0, 0);
127 s_odc_tess_work_buf = NULL;
130pi_ocpnDC::pi_ocpnDC()
131 : glcanvas(NULL), dc(NULL), m_pen(wxNullPen), m_brush(wxNullBrush) {
132#if wxUSE_GRAPHICS_CONTEXT
138 s_odc_tess_work_buf = NULL;
140#ifdef USE_ANDROID_GLES2
145pi_ocpnDC::~pi_ocpnDC() {
146#if wxUSE_GRAPHICS_CONTEXT
151 free(s_odc_tess_work_buf);
155#ifdef USE_ANDROID_GLES2
161void pi_ocpnDC::Clear() {
166 wxBrush tmpBrush = m_brush;
168 SetBrush(wxBrush(glcanvas->GetBackgroundColour()));
169 glcanvas->GetSize(&w, &h);
170 DrawRectangle(0, 0, w, h);
176void pi_ocpnDC::SetBackground(
const wxBrush &brush) {
178 dc->SetBackground(brush);
181 glcanvas->SetBackgroundColour(brush.GetColour());
186void pi_ocpnDC::SetPen(
const wxPen &pen) {
188 if (pen == wxNullPen)
189 dc->SetPen(*wxTRANSPARENT_PEN);
196void pi_ocpnDC::SetBrush(
const wxBrush &brush) {
203void pi_ocpnDC::SetTextForeground(
const wxColour &colour) {
205 dc->SetTextForeground(colour);
207 m_textforegroundcolour = colour;
210void pi_ocpnDC::SetFont(
const wxFont &font) {
217const wxPen &pi_ocpnDC::GetPen()
const {
218 if (dc)
return dc->GetPen();
222const wxBrush &pi_ocpnDC::GetBrush()
const {
223 if (dc)
return dc->GetBrush();
227const wxFont &pi_ocpnDC::GetFont()
const {
228 if (dc)
return dc->GetFont();
232void pi_ocpnDC::GetSize(wxCoord *width, wxCoord *height)
const {
234 dc->GetSize(width, height);
237 glcanvas->GetSize(width, height);
242void pi_ocpnDC::SetGLAttrs(
bool highQuality) {
247 glEnable(GL_LINE_SMOOTH);
248 glEnable(GL_POLYGON_SMOOTH);
251 glDisable(GL_LINE_SMOOTH);
252 glDisable(GL_POLYGON_SMOOTH);
258void pi_ocpnDC::SetGLStipple()
const {
261#ifndef USE_ANDROID_GLES2
262 switch (m_pen.GetStyle()) {
263 case wxPENSTYLE_DOT: {
264 glLineStipple(1, 0x3333);
265 glEnable(GL_LINE_STIPPLE);
268 case wxPENSTYLE_LONG_DASH: {
269 glLineStipple(1, 0xFFF8);
270 glEnable(GL_LINE_STIPPLE);
273 case wxPENSTYLE_SHORT_DASH: {
274 glLineStipple(1, 0x3F3F);
275 glEnable(GL_LINE_STIPPLE);
278 case wxPENSTYLE_DOT_DASH: {
279 glLineStipple(1, 0x8FF1);
280 glEnable(GL_LINE_STIPPLE);
292void piDrawEndCap(
float x1,
float y1,
float t1,
float angle) {
293#ifndef USE_ANDROID_GLES2
294 const int steps = 16;
297 for (
int i = 0; i <= steps; i++) {
298 float a = angle + M_PI / 2 + M_PI / steps * i;
300 float xb = x1 + t1 / 2 * cos(a);
301 float yb = y1 + t1 / 2 * sin(a);
316void piDrawGLThickLine(
float x1,
float y1,
float x2,
float y2, wxPen pen,
320 float angle = atan2f(y2 - y1, x2 - x1);
321 float t1 = pen.GetWidth();
322 float t2sina1 = t1 / 2 * sinf(angle);
323 float t2cosa1 = t1 / 2 * cosf(angle);
325#ifndef USE_ANDROID_GLES2
326 glBegin(GL_TRIANGLES);
331 int n_dashes = pen.GetDashes(&dashes);
333 float lpix = sqrtf(powf((
float)(x1 - x2), 2) + powf((
float)(y1 - y2), 2));
337 float ldraw = t1 * dashes[0];
338 float lspace = t1 * dashes[1];
340 while (lrun < lpix) {
342 float xb = xa + ldraw * cosf(angle);
343 float yb = ya + ldraw * sinf(angle);
345 if ((lrun + ldraw) >= lpix)
351 glVertex2f(xa + t2sina1, ya - t2cosa1);
352 glVertex2f(xb + t2sina1, yb - t2cosa1);
353 glVertex2f(xb - t2sina1, yb + t2cosa1);
355 glVertex2f(xb - t2sina1, yb + t2cosa1);
356 glVertex2f(xa - t2sina1, ya + t2cosa1);
357 glVertex2f(xa + t2sina1, ya - t2cosa1);
364 xb = xa + lspace * cos(angle);
365 yb = ya + lspace * sin(angle);
372 glVertex2f(x1 + t2sina1, y1 - t2cosa1);
373 glVertex2f(x2 + t2sina1, y2 - t2cosa1);
374 glVertex2f(x2 - t2sina1, y2 + t2cosa1);
376 glVertex2f(x2 - t2sina1, y2 + t2cosa1);
377 glVertex2f(x1 - t2sina1, y1 + t2cosa1);
378 glVertex2f(x1 + t2sina1, y1 - t2cosa1);
382 if (pen.GetCap() == wxCAP_ROUND) {
383 piDrawEndCap(x1, y1, t1, angle);
384 piDrawEndCap(x2, y2, t1, angle + M_PI);
394 int n_dashes = pen.GetDashes(&dashes);
396 float lpix = sqrtf(powf((
float)(x1 - x2), 2) + powf((
float)(y1 - y2), 2));
400 float ldraw = t1 * dashes[0];
401 float lspace = t1 * dashes[1];
403 glUseProgram(pi_color_tri_shader_program);
408 glBindBuffer(GL_ARRAY_BUFFER, 0);
409 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
411 GLint pos = glGetAttribLocation(pi_color_tri_shader_program,
"position");
412 glEnableVertexAttribArray(pos);
413 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float), vert);
420 glGetUniformLocation(pi_color_tri_shader_program,
"TransformMatrix");
421 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)I);
423 wxColor c = pen.GetColour();
425 colorv[0] = c.Red() / float(256);
426 colorv[1] = c.Green() / float(256);
427 colorv[2] = c.Blue() / float(256);
428 colorv[3] = c.Alpha() / float(256);
430 GLint colloc = glGetUniformLocation(pi_color_tri_shader_program,
"color");
431 glUniform4fv(colloc, 1, colorv);
433 while (lrun < lpix) {
435 float xb = xa + ldraw * cosf(angle);
436 float yb = ya + ldraw * sinf(angle);
438 if ((lrun + ldraw) >= lpix)
444 vert[0] = xa + t2sina1;
445 vert[1] = ya - t2cosa1;
446 vert[2] = xb + t2sina1;
447 vert[3] = yb - t2cosa1;
448 vert[4] = xb - t2sina1;
449 vert[5] = yb + t2cosa1;
450 vert[6] = xb - t2sina1;
451 vert[7] = yb + t2cosa1;
452 vert[8] = xa - t2sina1;
453 vert[9] = ya + t2cosa1;
454 vert[10] = xa + t2sina1;
455 vert[11] = ya - t2cosa1;
457 glDrawArrays(GL_TRIANGLES, 0, 6);
464 xb = xa + lspace * cos(angle);
465 yb = ya + lspace * sin(angle);
473 vert[0] = x1 + t2sina1;
474 vert[1] = y1 - t2cosa1;
475 vert[2] = x2 + t2sina1;
476 vert[3] = y2 - t2cosa1;
477 vert[4] = x2 - t2sina1;
478 vert[5] = y2 + t2cosa1;
479 vert[6] = x2 - t2sina1;
480 vert[7] = y2 + t2cosa1;
481 vert[8] = x1 - t2sina1;
482 vert[9] = y1 + t2cosa1;
483 vert[10] = x1 + t2sina1;
484 vert[11] = y1 - t2cosa1;
486 glUseProgram(pi_color_tri_shader_program);
489 glBindBuffer(GL_ARRAY_BUFFER, 0);
490 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
492 GLint pos = glGetAttribLocation(pi_color_tri_shader_program,
"position");
493 glEnableVertexAttribArray(pos);
494 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float), vert);
501 glGetUniformLocation(pi_color_tri_shader_program,
"TransformMatrix");
502 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)I);
504 wxColor c = pen.GetColour();
506 colorv[0] = c.Red() / float(256);
507 colorv[1] = c.Green() / float(256);
508 colorv[2] = c.Blue() / float(256);
509 colorv[3] = c.Alpha() / float(256);
511 GLint colloc = glGetUniformLocation(pi_color_tri_shader_program,
"color");
512 glUniform4fv(colloc, 1, colorv);
514 glDrawArrays(GL_TRIANGLES, 0, 6);
531void pi_ocpnDC::DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2,
533 if (dc) dc->DrawLine(x1, y1, x2, y2);
535 else if (ConfigurePen()) {
536 bool b_draw_thick =
false;
538 float pen_width = wxMax(g_piGLMinSymbolLineWidth, m_pen.GetWidth());
546 glEnable(GL_LINE_SMOOTH);
549 if (pen_width > 1.0) {
551 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
552 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
553 if (pen_width > parms[1])
556 glLineWidth(pen_width);
558 glLineWidth(pen_width);
562 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
563 if (pen_width > parms[1])
566 glLineWidth(pen_width);
568 glLineWidth(pen_width);
571#ifdef USE_ANDROID_GLES2
573 piDrawGLThickLine(x1, y1, x2, y2, m_pen, b_hiqual);
575 glUseProgram(pi_color_tri_shader_program);
578 GLint pos = glGetAttribLocation(pi_color_tri_shader_program,
"position");
579 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float),
581 glEnableVertexAttribArray(pos);
589 colorv[0] = m_pen.GetColour().Red() / float(256);
590 colorv[1] = m_pen.GetColour().Green() / float(256);
591 colorv[2] = m_pen.GetColour().Blue() / float(256);
594 GLint colloc = glGetUniformLocation(pi_color_tri_shader_program,
"color");
595 glUniform4fv(colloc, 1, colorv);
598 int n_dashes = m_pen.GetDashes(&dashes);
600 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
601 float cosa = cosf(angle);
602 float sina = sinf(angle);
603 float t1 = m_pen.GetWidth();
605 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
609 float ldraw = t1 * dashes[0];
610 float lspace = t1 * dashes[1];
612 ldraw = wxMax(ldraw, 4.0);
613 lspace = wxMax(lspace, 4.0);
614 lpix = wxMin(lpix, 2000.0);
616 while (lrun < lpix) {
618 float xb = xa + ldraw * cosa;
619 float yb = ya + ldraw * sina;
621 if ((lrun + ldraw) >= lpix)
632 glDrawArrays(GL_LINES, 0, 2);
634 xa = xa + (lspace + ldraw) * cosa;
635 ya = ya + (lspace + ldraw) * sina;
636 lrun += lspace + ldraw;
645 glDrawArrays(GL_LINES, 0, 2);
651 piDrawGLThickLine(x1, y1, x2, y2, m_pen, b_hiqual);
654 int n_dashes = m_pen.GetDashes(&dashes);
656 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
657 float cosa = cosf(angle);
658 float sina = sinf(angle);
659 float t1 = m_pen.GetWidth();
661 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
665 float ldraw = t1 * dashes[0];
666 float lspace = t1 * dashes[1];
668 ldraw = wxMax(ldraw, 4.0);
669 lspace = wxMax(lspace, 4.0);
670 lpix = wxMin(lpix, 2000.0);
673 while (lrun < lpix) {
675 float xb = xa + ldraw * cosa;
676 float yb = ya + ldraw * sina;
678 if ((lrun + ldraw) >= lpix)
687 xa = xa + (lspace + ldraw) * cosa;
688 ya = ya + (lspace + ldraw) * sina;
689 lrun += lspace + ldraw;
701 glDisable(GL_LINE_STIPPLE);
704 glDisable(GL_LINE_SMOOTH);
712void piDrawGLThickLines(
int n, wxPoint points[], wxCoord xoffset,
713 wxCoord yoffset, wxPen pen,
bool b_hiqual) {
717#ifdef USE_ANDROID_GLES2
718 wxPoint p0 = points[0];
719 for (
int i = 1; i < n; i++) {
720 piDrawGLThickLine(p0.x + xoffset, p0.y + yoffset, points[i].x + xoffset,
721 points[i].y + yoffset, pen, b_hiqual);
729 if (pen.GetDashes(&dashes)) {
730 wxPoint p0 = points[0];
731 for (
int i = 1; i < n; i++) {
732 piDrawGLThickLine(p0.x + xoffset, p0.y + yoffset, points[i].x + xoffset,
733 points[i].y + yoffset, pen, b_hiqual);
740 wxPoint *cpoints =
new wxPoint[n];
741 cpoints[0] = points[0];
743 for (
int i = 1; i < n; i++) {
744 if (points[i].x != points[i - 1].x || points[i].y != points[i - 1].y)
745 cpoints[c++] = points[i];
752 float t1 = pen.GetWidth();
754 float x0 = cpoints[0].x, y0 = cpoints[0].y, x1 = cpoints[1].x,
756 float a0 = atan2f(y1 - y0, x1 - x0);
760 glBegin(GL_TRIANGLES);
762 float t2sina0 = t1 / 2 * sinf(a0);
763 float t2cosa0 = t1 / 2 * cosf(a0);
765 for (
int i = 1; i < c; i++) {
770 x2 = cpoints[i + 1].x, y2 = cpoints[i + 1].y;
771 a1 = atan2f(y2 - y1, x2 - x1);
777 float aa = (a0 + a1) / 2;
778 float diff = fabsf(a0 - a1);
779 if (diff > M_PI) diff -= 2 * (float)M_PI;
780 float rad = t1 / 2 / wxMax(cosf(diff / 2), .4);
782 float t2sina1 = rad * sinf(aa);
783 float t2cosa1 = rad * cosf(aa);
785 glVertex2f(x1 + t2sina1, y1 - t2cosa1);
786 glVertex2f(x1 - t2sina1, y1 + t2cosa1);
787 glVertex2f(x0 + t2sina0, y0 - t2cosa0);
789 glVertex2f(x0 - t2sina0, y0 + t2cosa0);
790 glVertex2f(x0 + t2sina0, y0 - t2cosa0);
792 float dot = t2sina0 * t2sina1 + t2cosa0 * t2cosa1;
794 glVertex2f(x1 - t2sina1, y1 + t2cosa1);
796 glVertex2f(x1 + t2sina1, y1 - t2cosa1);
801 t2sina0 = t2sina1, t2cosa0 = t2cosa1;
804 if (pen.GetCap() == wxCAP_ROUND) {
805 piDrawEndCap(x0, y0, t1, a0);
806 piDrawEndCap(x0, y0, t1, a0 + M_PI);
818void pi_ocpnDC::DrawLines(
int n, wxPoint points[], wxCoord xoffset,
819 wxCoord yoffset,
bool b_hiqual) {
820 if (dc) dc->DrawLines(n, points, xoffset, yoffset);
822 else if (ConfigurePen()) {
827 SetGLAttrs(b_hiqual);
829 bool b_draw_thick =
false;
831 glDisable(GL_LINE_STIPPLE);
837 if (m_pen.GetWidth() > 1) {
839 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
840 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
842 if (m_pen.GetWidth() > parms[1])
845 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, m_pen.GetWidth()));
847 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, 1));
849 if (m_pen.GetWidth() > 1) {
851 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
852 if (m_pen.GetWidth() > parms[1])
855 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, m_pen.GetWidth()));
857 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, 1));
861 piDrawGLThickLines(n, points, xoffset, yoffset, m_pen, b_hiqual);
864 glDisable(GL_LINE_STIPPLE);
865 glDisable(GL_POLYGON_SMOOTH);
872#ifndef USE_ANDROID_GLES2
874 glBegin(GL_LINE_STRIP);
875 for (
int i = 0; i < n; i++)
876 glVertex2i(points[i].x + xoffset, points[i].y + yoffset);
882 if (workBufSize < (
size_t)n * 2) {
883 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
887 for (
int i = 0; i < n; i++) {
888 workBuf[i * 2] = points[i].x + xoffset;
889 workBuf[(i * 2) + 1] = points[i].y + yoffset;
892 glUseProgram(pi_color_tri_shader_program);
894 GLint pos = glGetAttribLocation(pi_color_tri_shader_program,
"position");
895 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float),
897 glEnableVertexAttribArray(pos);
904 colorv[0] = m_pen.GetColour().Red() / float(256);
905 colorv[1] = m_pen.GetColour().Green() / float(256);
906 colorv[2] = m_pen.GetColour().Blue() / float(256);
907 colorv[3] = m_pen.GetColour().Alpha() / float(256);
910 GLint colloc = glGetUniformLocation(pi_color_tri_shader_program,
"color");
911 glUniform4fv(colloc, 1, colorv);
913 glDrawArrays(GL_LINE_STRIP, 0, n);
918 glDisable(GL_LINE_STIPPLE);
919 glDisable(GL_POLYGON_SMOOTH);
926void pi_ocpnDC::StrokeLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) {
927#if wxUSE_GRAPHICS_CONTEXT
929 pgc->SetPen(dc->GetPen());
930 pgc->StrokeLine(x1, y1, x2, y2);
932 dc->CalcBoundingBox(x1, y1);
933 dc->CalcBoundingBox(x2, y2);
936 DrawLine(x1, y1, x2, y2,
true);
939void pi_ocpnDC::StrokeLines(
int n, wxPoint *points) {
943#if wxUSE_GRAPHICS_CONTEXT
945 wxPoint2DDouble *dPoints =
946 (wxPoint2DDouble *)malloc(n *
sizeof(wxPoint2DDouble));
947 for (
int i = 0; i < n; i++) {
948 dPoints[i].m_x = points[i].x;
949 dPoints[i].m_y = points[i].y;
951 pgc->SetPen(dc->GetPen());
952 pgc->StrokeLines(n, dPoints);
956 DrawLines(n, points, 0, 0,
true);
959void pi_ocpnDC::DrawGLLineArray(
int n,
float *vertex_array,
float *color_array,
962 if (ConfigurePen()) {
967 SetGLAttrs(b_hiqual);
969 bool b_draw_thick =
false;
971 glDisable(GL_LINE_STIPPLE);
977 if (m_pen.GetWidth() > 1) {
983 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, m_pen.GetWidth()));
985 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, 1));
987 if (m_pen.GetWidth() > 1) {
990 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, m_pen.GetWidth()));
992 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, 1));
995#ifndef USE_ANDROID_GLES2
1005 glUseProgram(pi_colorv_tri_shader_program);
1007 GLint pos = glGetAttribLocation(pi_colorv_tri_shader_program,
"position");
1008 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float),
1010 glEnableVertexAttribArray(pos);
1012 GLint colloc = glGetAttribLocation(pi_colorv_tri_shader_program,
"colorv");
1013 glVertexAttribPointer(colloc, 4, GL_FLOAT, GL_FALSE, 4 *
sizeof(
float),
1015 glEnableVertexAttribArray(colloc);
1017 glDrawArrays(GL_LINES, 0, n);
1022 glDisable(GL_LINE_STIPPLE);
1023 glDisable(GL_POLYGON_SMOOTH);
1024 glDisable(GL_BLEND);
1030void pi_ocpnDC::DrawRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h) {
1031 if (dc) dc->DrawRectangle(x, y, w, h);
1034#ifndef USE_ANDROID_GLES2
1035 if (ConfigureBrush()) {
1038 glVertex2i(x + w, y);
1039 glVertex2i(x + w, y + h);
1040 glVertex2i(x, y + h);
1044 if (ConfigurePen()) {
1045 glBegin(GL_LINE_LOOP);
1047 glVertex2i(x + w, y);
1048 glVertex2i(x + w, y + h);
1049 glVertex2i(x, y + h);
1058static void drawrrhelper(wxCoord x0, wxCoord y0, wxCoord r,
int quadrant,
1061#ifndef USE_ANDROID_GLES2
1062 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
1066 x = r, y = 0, dx = 0, dy = -rs, ddx = -rss, ddy = rss;
1069 x = 0, y = -r, dx = -rs, dy = 0, ddx = rss, ddy = rss;
1072 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
1075 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
1081 for (
int i = 0; i < steps; i++) {
1082 glVertex2i(x0 + floor(x), y0 + floor(y));
1083 x += dx + ddx / 2, y += dy + ddy / 2;
1084 dx += ddx, dy += ddy;
1086 glVertex2i(x0 + floor(x), y0 + floor(y));
1091void pi_ocpnDC::drawrrhelperGLES2(wxCoord x0, wxCoord y0, wxCoord r,
1092 int quadrant,
int steps) {
1094 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
1098 x = r, y = 0, dx = 0, dy = -rs, ddx = -rss, ddy = rss;
1101 x = 0, y = -r, dx = -rs, dy = 0, ddx = rss, ddy = rss;
1104 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
1107 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
1113 for (
int i = 0; i < steps; i++) {
1114 workBuf[workBufIndex++] = x0 + floor(x);
1115 workBuf[workBufIndex++] = y0 + floor(y);
1117 x += dx + ddx / 2, y += dy + ddy / 2;
1118 dx += ddx, dy += ddy;
1121 workBuf[workBufIndex++] = x0 + floor(x);
1122 workBuf[workBufIndex++] = y0 + floor(y);
1126void pi_ocpnDC::DrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
1128 if (dc) dc->DrawRoundedRectangle(x, y, w, h, r);
1132 int steps = ceil(sqrt((
float)r));
1134 wxCoord x1 = x + r, x2 = x + w - r;
1135 wxCoord y1 = y + r, y2 = y + h - r;
1137#ifdef USE_ANDROID_GLES2
1140 size_t bufReq = steps * 8 * 2 *
sizeof(float);
1142 if (workBufSize < bufReq) {
1143 workBuf = (
float *)realloc(workBuf, bufReq);
1144 workBufSize = bufReq;
1148 drawrrhelperGLES2(x2, y1, r, 0, steps);
1149 drawrrhelperGLES2(x1, y1, r, 1, steps);
1150 drawrrhelperGLES2(x1, y2, r, 2, steps);
1151 drawrrhelperGLES2(x2, y2, r, 3, steps);
1153 glUseProgram(pi_color_tri_shader_program);
1157 glGetAttribLocation(pi_color_tri_shader_program,
"position");
1160 glBindBuffer(GL_ARRAY_BUFFER, 0);
1161 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1163 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, workBuf);
1164 glEnableVertexAttribArray(mPosAttrib);
1168 bcolorv[0] = m_brush.GetColour().Red() / float(256);
1169 bcolorv[1] = m_brush.GetColour().Green() / float(256);
1170 bcolorv[2] = m_brush.GetColour().Blue() / float(256);
1171 bcolorv[3] = m_brush.GetColour().Alpha() / float(256);
1173 GLint bcolloc = glGetUniformLocation(pi_color_tri_shader_program,
"color");
1174 glUniform4fv(bcolloc, 1, bcolorv);
1183 mat4x4_rotate_Z(Q, I, angle);
1190 glGetUniformLocation(pi_color_tri_shader_program,
"TransformMatrix");
1191 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)Q);
1194 glDrawArrays(GL_TRIANGLE_FAN, 0, workBufIndex / 2);
1198 mat4x4_identity(IM);
1200 glGetUniformLocation(pi_color_tri_shader_program,
"TransformMatrix");
1201 glUniformMatrix4fv(matlocf, 1, GL_FALSE, (
const GLfloat *)IM);
1204 if (ConfigureBrush()) {
1205 glBegin(GL_TRIANGLE_FAN);
1206 drawrrhelper(x2, y1, r, 0, steps);
1207 drawrrhelper(x1, y1, r, 1, steps);
1208 drawrrhelper(x1, y2, r, 2, steps);
1209 drawrrhelper(x2, y2, r, 3, steps);
1213 if (ConfigurePen()) {
1214 glBegin(GL_LINE_LOOP);
1215 drawrrhelper(x2, y1, r, 0, steps);
1216 drawrrhelper(x1, y1, r, 1, steps);
1217 drawrrhelper(x1, y2, r, 2, steps);
1218 drawrrhelper(x2, y2, r, 3, steps);
1226void pi_ocpnDC::DrawCircle(wxCoord x, wxCoord y, wxCoord radius) {
1227#ifdef USE_ANDROID_GLES2
1233 coords[0] = x - radius;
1234 coords[1] = y + radius;
1235 coords[2] = x + radius;
1236 coords[3] = y + radius;
1237 coords[4] = x - radius;
1238 coords[5] = y - radius;
1239 coords[6] = x + radius;
1240 coords[7] = y - radius;
1242 glUseProgram(pi_circle_filled_shader_program);
1246 glGetAttribLocation(pi_circle_filled_shader_program,
"aPos");
1249 glBindBuffer(GL_ARRAY_BUFFER, 0);
1250 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1252 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, coords);
1253 glEnableVertexAttribArray(mPosAttrib);
1257 glGetUniformLocation(pi_circle_filled_shader_program,
"circle_radius");
1258 glUniform1f(radiusloc, radius);
1262 glGetUniformLocation(pi_circle_filled_shader_program,
"circle_center");
1265 ctrv[1] = m_vpSize.y - y;
1266 glUniform2fv(centerloc, 1, ctrv);
1270 colorv[0] = m_brush.GetColour().Red() / float(256);
1271 colorv[1] = m_brush.GetColour().Green() / float(256);
1272 colorv[2] = m_brush.GetColour().Blue() / float(256);
1273 colorv[3] = (m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT) ? 0.0 : 1.0;
1276 glGetUniformLocation(pi_circle_filled_shader_program,
"circle_color");
1277 glUniform4fv(colloc, 1, colorv);
1281 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1282 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1283 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1284 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1287 glGetUniformLocation(pi_circle_filled_shader_program,
"border_color");
1288 glUniform4fv(bcolloc, 1, bcolorv);
1291 GLint borderWidthloc =
1292 glGetUniformLocation(pi_circle_filled_shader_program,
"border_width");
1293 glUniform1f(borderWidthloc, m_pen.GetWidth());
1301 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1304 glDisable(GL_BLEND);
1307 DrawEllipse(x - radius, y - radius, 2 * radius, 2 * radius);
1311void pi_ocpnDC::StrokeCircle(wxCoord x, wxCoord y, wxCoord radius) {
1312#if wxUSE_GRAPHICS_CONTEXT
1314 wxGraphicsPath gpath = pgc->CreatePath();
1315 gpath.AddCircle(x, y, radius);
1317 pgc->SetPen(GetPen());
1318 pgc->SetBrush(GetBrush());
1319 pgc->DrawPath(gpath);
1322 dc->CalcBoundingBox(x + radius + 2, y + radius + 2);
1323 dc->CalcBoundingBox(x - radius - 2, y - radius - 2);
1326 DrawCircle(x, y, radius);
1329void pi_ocpnDC::DrawEllipse(wxCoord x, wxCoord y, wxCoord width,
1331 if (dc) dc->DrawEllipse(x, y, width, height);
1334 float r1 = width / 2, r2 = height / 2;
1335 float cx = x + r1, cy = y + r2;
1341 float steps = floorf(
1342 wxMax(sqrtf(sqrtf((
float)(width * width + height * height))), 1) *
1345#ifndef USE_ANDROID_GLES2
1346 if (ConfigureBrush()) {
1347 glBegin(GL_TRIANGLE_FAN);
1349 for (
float a = 0; a <= 2 * M_PI + M_PI / steps; a += 2 * M_PI / steps)
1350 glVertex2f(cx + r1 * sinf(a), cy + r2 * cosf(a));
1354 if (ConfigurePen()) {
1355 glBegin(GL_LINE_LOOP);
1356 for (
float a = 0; a < 2 * M_PI - M_PI / steps; a += 2 * M_PI / steps)
1357 glVertex2f(cx + r1 * sinf(a), cy + r2 * cosf(a));
1362 glDisable(GL_BLEND);
1367void pi_ocpnDC::DrawPolygon(
int n, wxPoint points[], wxCoord xoffset,
1368 wxCoord yoffset,
float scale,
float angle) {
1369 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1379#ifdef USE_ANDROID_GLES2
1384 DrawPolygonTessellated(n, points, xoffset, yoffset);
1388 if (workBufSize < (
size_t)n * 2) {
1389 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
1390 workBufSize = n * 4;
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 glUseProgram(pi_color_tri_shader_program);
1402 glGetAttribLocation(pi_color_tri_shader_program,
"position");
1405 glBindBuffer(GL_ARRAY_BUFFER, 0);
1406 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1408 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, workBuf);
1409 glEnableVertexAttribArray(mPosAttrib);
1413 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1414 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1415 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1416 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1419 glGetUniformLocation(pi_color_tri_shader_program,
"color");
1420 glUniform4fv(bcolloc, 1, bcolorv);
1425 mat4x4_rotate_Z(Q, I, angle);
1432 glGetUniformLocation(pi_color_tri_shader_program,
"TransformMatrix");
1433 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)Q);
1436 glDrawArrays(GL_LINE_LOOP, 0, n);
1439 bcolorv[0] = m_brush.GetColour().Red() / float(256);
1440 bcolorv[1] = m_brush.GetColour().Green() / float(256);
1441 bcolorv[2] = m_brush.GetColour().Blue() / float(256);
1442 bcolorv[3] = m_brush.GetColour().Alpha() / float(256);
1444 glUniform4fv(bcolloc, 1, bcolorv);
1449 float x1 = workBuf[4];
1450 float y1 = workBuf[5];
1451 workBuf[4] = workBuf[6];
1452 workBuf[5] = workBuf[7];
1456 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1457 }
else if (n == 3) {
1458 glDrawArrays(GL_TRIANGLES, 0, 3);
1463 mat4x4_identity(IM);
1465 glGetUniformLocation(pi_color_tri_shader_program,
"TransformMatrix");
1466 glUniformMatrix4fv(matlocf, 1, GL_FALSE, (
const GLfloat *)IM);
1471 if (ConfigureBrush()) {
1472 glEnable(GL_POLYGON_SMOOTH);
1473 glBegin(GL_POLYGON);
1474 for (
int i = 0; i < n; i++)
1475 glVertex2f((points[i].x *
scale) + xoffset,
1476 (points[i].y *
scale) + yoffset);
1478 glDisable(GL_POLYGON_SMOOTH);
1481 if (ConfigurePen()) {
1482 glEnable(GL_LINE_SMOOTH);
1483 glBegin(GL_LINE_LOOP);
1484 for (
int i = 0; i < n; i++)
1485 glVertex2f((points[i].x *
scale) + xoffset,
1486 (points[i].y *
scale) + yoffset);
1488 glDisable(GL_LINE_SMOOTH);
1513#ifndef USE_ANDROID_GLES2
1521void APIENTRY pi_ocpnDCcombineCallback(GLdouble coords[3],
1522 GLdouble *vertex_data[4],
1523 GLfloat weight[4], GLdouble **dataOut) {
1526 vertex =
new GLvertex();
1527 pi_gTesselatorVertices.Add(vertex);
1529 vertex->info.x = coords[0];
1530 vertex->info.y = coords[1];
1531 vertex->info.z = coords[2];
1533 for (
int i = 3; i < 6; i++) {
1535 weight[0] * vertex_data[0][i] + weight[1] * vertex_data[1][i];
1538 *dataOut = &(vertex->data[0]);
1541void APIENTRY ocpnDCvertexCallback(GLvoid *arg) {
1543 vertex = (GLvertex *)arg;
1544 glVertex2f((
float)vertex->info.x, (
float)vertex->info.y);
1547void APIENTRY ocpnDCerrorCallback(GLenum errorCode) {
1548 const GLubyte *estring;
1549 estring = gluErrorString(errorCode);
1553void APIENTRY ocpnDCbeginCallback(GLenum type) { glBegin(type); }
1555void APIENTRY ocpnDCendCallback() { glEnd(); }
1560#ifdef USE_ANDROID_GLES2
1562static std::list<double *> odc_combine_work_data;
1563static void pi_odc_combineCallbackD(GLdouble coords[3],
1564 GLdouble *vertex_data[4], GLfloat weight[4],
1565 GLdouble **dataOut,
void *data) {
1572void pi_odc_vertexCallbackD_GLSL(GLvoid *vertex,
void *data) {
1576 if (pDC->s_odc_tess_vertex_idx > pDC->s_odc_tess_buf_len - 8) {
1577 int new_buf_len = pDC->s_odc_tess_buf_len + 100;
1578 GLfloat *tmp = pDC->s_odc_tess_work_buf;
1580 pDC->s_odc_tess_work_buf = (GLfloat *)realloc(
1581 pDC->s_odc_tess_work_buf, new_buf_len *
sizeof(GLfloat));
1582 if (NULL == pDC->s_odc_tess_work_buf) {
1586 pDC->s_odc_tess_buf_len = new_buf_len;
1589 GLdouble *pointer = (GLdouble *)vertex;
1591 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[0];
1592 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[1];
1594 pDC->s_odc_nvertex++;
1597void pi_odc_beginCallbackD_GLSL(GLenum mode,
void *data) {
1599 pDC->s_odc_tess_vertex_idx_this = pDC->s_odc_tess_vertex_idx;
1600 pDC->s_odc_tess_mode = mode;
1601 pDC->s_odc_nvertex = 0;
1604void pi_odc_endCallbackD_GLSL(
void *data) {
1610 glUseProgram(pi_color_tri_shader_program);
1613 glBindBuffer(GL_ARRAY_BUFFER, 0);
1614 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1616 float *bufPt = &(pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx_this]);
1617 GLint pos = glGetAttribLocation(pi_color_tri_shader_program,
"position");
1618 glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(
float), bufPt);
1619 glEnableVertexAttribArray(pos);
1627 wxColour c = pDC->GetBrush().GetColour();
1629 colorv[0] = c.Red() / float(256);
1630 colorv[1] = c.Green() / float(256);
1631 colorv[2] = c.Blue() / float(256);
1632 colorv[3] = c.Alpha() / float(256);
1634 GLint colloc = glGetUniformLocation(pi_color_tri_shader_program,
"color");
1635 glUniform4fv(colloc, 1, colorv);
1637 glDrawArrays(pDC->s_odc_tess_mode, 0, pDC->s_odc_nvertex);
1644void pi_ocpnDC::DrawPolygonTessellated(
int n, wxPoint points[], wxCoord xoffset,
1646 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1649#if !defined(ocpnUSE_GLES) || \
1650 defined(USE_ANDROID_GLES2)
1654 DrawPolygon(n, points, xoffset, yoffset);
1658#ifdef USE_ANDROID_GLES2
1659 m_tobj = gluNewTess();
1660 s_odc_tess_vertex_idx = 0;
1662 gluTessCallback(m_tobj, GLU_TESS_VERTEX_DATA,
1663 (_GLUfuncptr)&pi_odc_vertexCallbackD_GLSL);
1664 gluTessCallback(m_tobj, GLU_TESS_BEGIN_DATA,
1665 (_GLUfuncptr)&pi_odc_beginCallbackD_GLSL);
1666 gluTessCallback(m_tobj, GLU_TESS_END_DATA,
1667 (_GLUfuncptr)&pi_odc_endCallbackD_GLSL);
1668 gluTessCallback(m_tobj, GLU_TESS_COMBINE_DATA,
1669 (_GLUfuncptr)&pi_odc_combineCallbackD);
1672 gluTessNormal(m_tobj, 0, 0, 1);
1673 gluTessProperty(m_tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
1675 if (ConfigureBrush()) {
1676 gluTessBeginPolygon(m_tobj,
this);
1677 gluTessBeginContour(m_tobj);
1679 for (
int i = 0; i < n; i++) {
1680 double *p =
new double[6];
1681 p[0] = points[i].x, p[1] = points[i].y, p[2] = 0;
1682 gluTessVertex(m_tobj, p, p);
1685 gluTessEndContour(m_tobj);
1686 gluTessEndPolygon(m_tobj);
1689 gluDeleteTess(m_tobj);
1698 static GLUtesselator *tobj = NULL;
1699 if (!tobj) tobj = gluNewTess();
1701 gluTessCallback(tobj, GLU_TESS_VERTEX, (_GLUfuncptr)&ocpnDCvertexCallback);
1702 gluTessCallback(tobj, GLU_TESS_BEGIN, (_GLUfuncptr)&ocpnDCbeginCallback);
1703 gluTessCallback(tobj, GLU_TESS_END, (_GLUfuncptr)&ocpnDCendCallback);
1704 gluTessCallback(tobj, GLU_TESS_COMBINE,
1705 (_GLUfuncptr)&pi_ocpnDCcombineCallback);
1706 gluTessCallback(tobj, GLU_TESS_ERROR, (_GLUfuncptr)&ocpnDCerrorCallback);
1708 gluTessNormal(tobj, 0, 0, 1);
1709 gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
1711 if (ConfigureBrush()) {
1712 gluTessBeginPolygon(tobj, NULL);
1713 gluTessBeginContour(tobj);
1715 for (
int i = 0; i < n; i++) {
1716 GLvertex *vertex =
new GLvertex();
1717 pi_gTesselatorVertices.Add(vertex);
1718 vertex->info.x = (GLdouble)points[i].x;
1719 vertex->info.y = (GLdouble)points[i].y;
1720 vertex->info.z = (GLdouble)0.0;
1721 vertex->info.r = (GLdouble)0.0;
1722 vertex->info.g = (GLdouble)0.0;
1723 vertex->info.b = (GLdouble)0.0;
1724 gluTessVertex(tobj, (GLdouble *)vertex, (GLdouble *)vertex);
1726 gluTessEndContour(tobj);
1727 gluTessEndPolygon(tobj);
1730 for (
unsigned int i = 0; i < pi_gTesselatorVertices.Count(); i++)
1731 delete (GLvertex *)pi_gTesselatorVertices.Item(i);
1732 pi_gTesselatorVertices.Clear();
1734 gluDeleteTess(tobj);
1740void pi_ocpnDC::StrokePolygon(
int n, wxPoint points[], wxCoord xoffset,
1741 wxCoord yoffset,
float scale) {
1742#if wxUSE_GRAPHICS_CONTEXT
1744 wxGraphicsPath gpath = pgc->CreatePath();
1745 gpath.MoveToPoint(points[0].x + xoffset, points[0].y + yoffset);
1746 for (
int i = 1; i < n; i++)
1747 gpath.AddLineToPoint(points[i].x + xoffset, points[i].y + yoffset);
1748 gpath.AddLineToPoint(points[0].x + xoffset, points[0].y + yoffset);
1750 pgc->SetPen(GetPen());
1751 pgc->SetBrush(GetBrush());
1752 pgc->DrawPath(gpath);
1754 for (
int i = 0; i < n; i++)
1755 dc->CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset);
1758 DrawPolygon(n, points, xoffset, yoffset,
scale);
1761void pi_ocpnDC::DrawBitmap(
const wxBitmap &bitmap, wxCoord x, wxCoord y,
1764 if (x < 0 || y < 0) {
1765 int dx = (x < 0 ? -x : 0);
1766 int dy = (y < 0 ? -y : 0);
1767 int w = bitmap.GetWidth() - dx;
1768 int h = bitmap.GetHeight() - dy;
1770 if (w <= 0 || h <= 0)
return;
1771 wxBitmap newBitmap = bitmap.GetSubBitmap(wxRect(dx, dy, w, h));
1778 if (dc) dc->DrawBitmap(bmp, x, y, usemask);
1786#ifndef USE_ANDROID_GLES2
1787 wxImage image = bmp.ConvertToImage();
1788 int w = image.GetWidth(), h = image.GetHeight();
1791 unsigned char *d = image.GetData();
1792 unsigned char *a = image.GetAlpha();
1794 unsigned char mr, mg, mb;
1795 if (!image.GetOrFindMaskColour(&mr, &mg, &mb) && !a) {
1796 printf(
"trying to use mask to draw a bitmap without alpha or mask\n");
1800 if (image.HasMask()) a = 0;
1803 unsigned char *e =
new unsigned char[4 * w * h];
1805 for (
int y = 0; y < h; y++)
1806 for (
int x = 0; x < w; x++) {
1807 unsigned char r, g, b;
1808 int off = (y * image.GetWidth() + x);
1818 a ? a[off] : ((r == mr) && (g == mg) && (b == mb) ? 0 : 255);
1824 glColor4f(1, 1, 1, 1);
1825 GLDrawBlendData(x, y, w, h, GL_RGBA, e);
1828 glRasterPos2i(x, y);
1830 if (image.GetData())
1831 glDrawPixels(w, h, GL_RGB, GL_UNSIGNED_BYTE, image.GetData());
1840void pi_ocpnDC::DrawText(
const wxString &text, wxCoord x, wxCoord y) {
1841 if (dc) dc->DrawText(text, x, y);
1848 m_texfont.Build(m_font);
1849 m_texfont.GetTextExtent(text, &w, &h);
1853 glEnable(GL_TEXTURE_2D);
1854 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1856#ifndef USE_ANDROID_GLES2
1857 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1859 glTranslatef(x, y, 0);
1861 glColor3ub(m_textforegroundcolour.Red(), m_textforegroundcolour.Green(),
1862 m_textforegroundcolour.Blue());
1864 m_texfont.RenderString(text);
1867 m_texfont.RenderString(text, x, y);
1869 glDisable(GL_TEXTURE_2D);
1870 glDisable(GL_BLEND);
1874 sdc.SetFont(m_font);
1875 sdc.GetTextExtent(text, &w, &h, NULL, NULL, &m_font);
1880 temp_dc.SelectObject(bmp);
1883 temp_dc.SetBackground(wxBrush(wxColour(0, 0, 0)));
1887 temp_dc.SetFont(m_font);
1888 temp_dc.SetTextForeground(wxColour(255, 255, 255));
1889 temp_dc.DrawText(text, 0, 0);
1890 temp_dc.SelectObject(wxNullBitmap);
1894 wxImage image = bmp.ConvertToImage();
1897 int dx = (x < 0 ? -x : 0);
1898 int dy = (y < 0 ? -y : 0);
1899 w = bmp.GetWidth() - dx;
1900 h = bmp.GetHeight() - dy;
1902 if (w <= 0 || h <= 0)
return;
1903 image = image.GetSubImage(wxRect(dx, dy, w, h));
1908 unsigned char *data =
new unsigned char[w * h * 4];
1909 unsigned char *im = image.GetData();
1912 unsigned int r = m_textforegroundcolour.Red();
1913 unsigned int g = m_textforegroundcolour.Green();
1914 unsigned int b = m_textforegroundcolour.Blue();
1915 for (
int i = 0; i < h; i++) {
1916 for (
int j = 0; j < w; j++) {
1917 unsigned int index = ((i * w) + j) * 4;
1919 data[index + 1] = g;
1920 data[index + 2] = b;
1921 data[index + 3] = im[((i * w) + j) * 3];
1926 glColor4ub( 255, 255, 255, 255 );
1927 glEnable( GL_BLEND );
1928 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1929 glRasterPos2i( x, y );
1930 glPixelZoom( 1, -1 );
1931 glDrawPixels( w, h, GL_RGBA, GL_UNSIGNED_BYTE, data );
1932 glPixelZoom( 1, 1 );
1933 glDisable( GL_BLEND );
1935 unsigned int texobj;
1937 glGenTextures(1, &texobj);
1938 glBindTexture(GL_TEXTURE_2D, texobj);
1940 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1941 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1943 int TextureWidth = NextPow2(w);
1944 int TextureHeight = NextPow2(h);
1945 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TextureWidth, TextureHeight, 0,
1946 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1947 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
1950 glEnable(GL_TEXTURE_2D);
1952 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1954#ifndef USE_ANDROID_GLES2
1955 glColor3ub(0, 0, 0);
1957 float u = (float)w / TextureWidth, v = (
float)h / TextureHeight;
1962 glVertex2f(x + w, y);
1964 glVertex2f(x + w, y + h);
1966 glVertex2f(x, y + h);
1970 glDisable(GL_BLEND);
1971 glDisable(GL_TEXTURE_2D);
1973 glDeleteTextures(1, &texobj);
1981void pi_ocpnDC::GetTextExtent(
const wxString &
string, wxCoord *w, wxCoord *h,
1982 wxCoord *descent, wxCoord *externalLeading,
1989 dc->GetTextExtent(
string, w, h, descent, externalLeading, font);
1992 if (font) f = *font;
1997 m_texfont.GetTextExtent(
string, w, h);
2000 temp_dc.GetTextExtent(
string, w, h, descent, externalLeading, &f);
2004 temp_dc.GetTextExtent(
string, w, h, descent, externalLeading, &f);
2010 if (w && (*w > 2000)) *w = 2000;
2011 if (h && (*h > 500)) *h = 500;
2014void pi_ocpnDC::ResetBoundingBox() {
2015 if (dc) dc->ResetBoundingBox();
2018void pi_ocpnDC::CalcBoundingBox(wxCoord x, wxCoord y) {
2019 if (dc) dc->CalcBoundingBox(x, y);
2022bool pi_ocpnDC::ConfigurePen() {
2023 if (!m_pen.IsOk())
return false;
2024 if (m_pen == *wxTRANSPARENT_PEN)
return false;
2026 wxColour c = m_pen.GetColour();
2027 int width = m_pen.GetWidth();
2029#ifndef USE_ANDROID_GLES2
2030 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
2031 glLineWidth(wxMax(g_piGLMinSymbolLineWidth, width));
2037bool pi_ocpnDC::ConfigureBrush() {
2038 if (m_brush == wxNullBrush || m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT)
2041#ifndef USE_ANDROID_GLES2
2042 wxColour c = m_brush.GetColour();
2043 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
2049void pi_ocpnDC::GLDrawBlendData(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
2050 int format,
const unsigned char *data) {
2052#ifndef USE_ANDROID_GLES2
2054 glRasterPos2i(x, y);
2056 glDrawPixels(w, h, format, GL_UNSIGNED_BYTE, data);
2058 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.
wxString GetLocaleCanonicalName()
Gets system locale canonical name.
Graphics abstraction layer on top of wxDC or OpenGL.