/*========================================================================= Program: Visualization Toolkit Module: vtkContext2D.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkContext2D.h" #include "vtkBrush.h" #include "vtkContextDevice2D.h" #include "vtkFloatArray.h" #include "vtkPen.h" #include "vtkPoints2D.h" #include "vtkTextProperty.h" #include "vtkTransform2D.h" #include "vtkUnsignedCharArray.h" #include "vtkVector.h" #include "vtkObjectFactory.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include //------------------------------------------------------------------------------ vtkStandardNewMacro(vtkContext2D); //------------------------------------------------------------------------------ bool vtkContext2D::Begin(vtkContextDevice2D* device) { if (this->Device == device) { // Handle the case where the same device is set multiple times return true; } else if (this->Device) { this->Device->Delete(); } this->Device = device; this->Device->Register(this); this->Modified(); return true; } //------------------------------------------------------------------------------ bool vtkContext2D::End() { if (this->Device) { this->Device->End(); this->Device->Delete(); this->Device = nullptr; this->Modified(); return true; } return true; } //------------------------------------------------------------------------------ bool vtkContext2D::GetBufferIdMode() const { return this->BufferId != nullptr; } //------------------------------------------------------------------------------ void vtkContext2D::BufferIdModeBegin(vtkAbstractContextBufferId* bufferId) { assert("pre: not_yet" && !this->GetBufferIdMode()); assert("pre: bufferId_exists" && bufferId != nullptr); this->BufferId = bufferId; this->Device->BufferIdModeBegin(bufferId); assert("post: started" && this->GetBufferIdMode()); } //------------------------------------------------------------------------------ void vtkContext2D::BufferIdModeEnd() { assert("pre: started" && this->GetBufferIdMode()); this->Device->BufferIdModeEnd(); this->BufferId = nullptr; assert("post: done" && !this->GetBufferIdMode()); } //------------------------------------------------------------------------------ void vtkContext2D::DrawLine(float x1, float y1, float x2, float y2) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } float x[] = { x1, y1, x2, y2 }; this->Device->DrawPoly(&x[0], 2); } //------------------------------------------------------------------------------ void vtkContext2D::DrawLine(float p[4]) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } this->Device->DrawPoly(&p[0], 2); } //------------------------------------------------------------------------------ void vtkContext2D::DrawLine(vtkPoints2D* points) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } if (points->GetNumberOfPoints() < 2) { vtkErrorMacro(<< "Attempted to paint a line with <2 points."); return; } float* f = vtkArrayDownCast(points->GetData())->GetPointer(0); this->Device->DrawPoly(f, 2); } //------------------------------------------------------------------------------ void vtkContext2D::DrawPoly(float* x, float* y, int n) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } float* p = new float[2 * n]; for (int i = 0; i < n; ++i) { p[2 * i] = x[i]; p[2 * i + 1] = y[i]; } this->Device->DrawPoly(p, n); delete[] p; } //------------------------------------------------------------------------------ void vtkContext2D::DrawPoly(vtkPoints2D* points) { // Construct an array with the correct coordinate packing for OpenGL. int n = static_cast(points->GetNumberOfPoints()); // If the points are of type float then call OpenGL directly float* f = vtkArrayDownCast(points->GetData())->GetPointer(0); this->DrawPoly(f, n); } //------------------------------------------------------------------------------ void vtkContext2D::DrawPoly(float* points, int n) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } if (n < 2) { vtkErrorMacro(<< "Attempted to paint a line with <2 points."); return; } this->Device->DrawPoly(points, n); } //------------------------------------------------------------------------------ void vtkContext2D::DrawPoly(float* points, int n, unsigned char* colors, int nc_comps) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } if (n < 2) { vtkErrorMacro(<< "Attempted to paint a line with <2 points."); return; } this->Device->DrawPoly(points, n, colors, nc_comps); } //------------------------------------------------------------------------------ void vtkContext2D::DrawLines(vtkPoints2D* points) { // Construct an array with the correct coordinate packing for OpenGL. int n = static_cast(points->GetNumberOfPoints()); // If the points are of type float then call OpenGL directly float* f = vtkArrayDownCast(points->GetData())->GetPointer(0); this->DrawLines(f, n); } //------------------------------------------------------------------------------ void vtkContext2D::DrawLines(float* points, int n) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } if (n < 2) { vtkErrorMacro(<< "Attempted to paint a line with <2 points."); return; } this->Device->DrawLines(points, n); } //------------------------------------------------------------------------------ void vtkContext2D::DrawPoint(float x, float y) { float p[] = { x, y }; this->DrawPoints(&p[0], 1); } //------------------------------------------------------------------------------ void vtkContext2D::DrawPoints(float* x, float* y, int n) { // Copy the points into an array and draw it. float* p = new float[2 * n]; for (int i = 0; i < n; ++i) { p[2 * i] = x[i]; p[2 * i + 1] = y[i]; } this->DrawPoints(&p[0], n); delete[] p; } //------------------------------------------------------------------------------ void vtkContext2D::DrawPoints(vtkPoints2D* points) { // Construct an array with the correct coordinate packing for OpenGL. int n = static_cast(points->GetNumberOfPoints()); // If the points are of type float then call OpenGL directly float* f = vtkArrayDownCast(points->GetData())->GetPointer(0); this->DrawPoints(f, n); } //------------------------------------------------------------------------------ void vtkContext2D::DrawPoints(float* points, int n) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } this->Device->DrawPoints(points, n); } //------------------------------------------------------------------------------ void vtkContext2D::DrawPointSprites(vtkImageData* sprite, vtkPoints2D* points) { // Construct an array with the correct coordinate packing for OpenGL. int n = static_cast(points->GetNumberOfPoints()); // If the points are of type float then call OpenGL directly float* f = vtkArrayDownCast(points->GetData())->GetPointer(0); this->DrawPointSprites(sprite, f, n); } //------------------------------------------------------------------------------ void vtkContext2D::DrawPointSprites( vtkImageData* sprite, vtkPoints2D* points, vtkUnsignedCharArray* colors) { // Construct an array with the correct coordinate packing for OpenGL. int n = static_cast(points->GetNumberOfPoints()); int nc = static_cast(colors->GetNumberOfTuples()); if (n != nc) { vtkErrorMacro(<< "Attempted to color points with array of wrong length"); return; } int nc_comps = static_cast(colors->GetNumberOfComponents()); // If the points are of type float then call OpenGL directly float* f = vtkArrayDownCast(points->GetData())->GetPointer(0); unsigned char* c = colors->GetPointer(0); this->DrawPointSprites(sprite, f, n, c, nc_comps); } //------------------------------------------------------------------------------ void vtkContext2D::DrawPointSprites( vtkImageData* sprite, float* points, int n, unsigned char* colors, int nc_comps) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } this->Device->DrawPointSprites(sprite, points, n, colors, nc_comps); } //------------------------------------------------------------------------------ void vtkContext2D::DrawPointSprites(vtkImageData* sprite, float* points, int n) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } this->Device->DrawPointSprites(sprite, points, n); } //------------------------------------------------------------------------------ void vtkContext2D::DrawMarkers( int shape, bool highlight, float* points, int n, unsigned char* colors, int nc_comps) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } this->Device->DrawMarkers(shape, highlight, points, n, colors, nc_comps); } //------------------------------------------------------------------------------ void vtkContext2D::DrawMarkers(int shape, bool highlight, float* points, int n) { this->DrawMarkers(shape, highlight, points, n, nullptr, 0); } //------------------------------------------------------------------------------ void vtkContext2D::DrawMarkers(int shape, bool highlight, vtkPoints2D* points) { // Construct an array with the correct coordinate packing for OpenGL. int n = static_cast(points->GetNumberOfPoints()); float* f = vtkArrayDownCast(points->GetData())->GetPointer(0); this->DrawMarkers(shape, highlight, f, n); } //------------------------------------------------------------------------------ void vtkContext2D::DrawMarkers( int shape, bool highlight, vtkPoints2D* points, vtkUnsignedCharArray* colors) { // Construct an array with the correct coordinate packing for OpenGL. int n = static_cast(points->GetNumberOfPoints()); int nc = static_cast(colors->GetNumberOfTuples()); if (n != nc) { vtkErrorMacro(<< "Attempted to color points with array of wrong length"); return; } int nc_comps = static_cast(colors->GetNumberOfComponents()); float* f = vtkArrayDownCast(points->GetData())->GetPointer(0); unsigned char* c = colors->GetPointer(0); this->DrawMarkers(shape, highlight, f, n, c, nc_comps); } //------------------------------------------------------------------------------ void vtkContext2D::DrawRect(float x, float y, float width, float height) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } float p[] = { x, y, x + width, y, x + width, y + height, x, y + height, x, y }; // Draw the filled area of the rectangle. this->Device->DrawQuad(&p[0], 4); // Draw the outline now. this->Device->DrawPoly(&p[0], 5); } //------------------------------------------------------------------------------ void vtkContext2D::DrawQuad( float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) { float p[] = { x1, y1, x2, y2, x3, y3, x4, y4 }; this->DrawQuad(&p[0]); } //------------------------------------------------------------------------------ void vtkContext2D::DrawQuad(float* p) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } // Draw the filled area of the quad. this->Device->DrawQuad(p, 4); // Draw the outline now. this->Device->DrawPoly(p, 4); float closeLine[] = { p[0], p[1], p[6], p[7] }; this->Device->DrawPoly(&closeLine[0], 2); } //------------------------------------------------------------------------------ void vtkContext2D::DrawQuadStrip(vtkPoints2D* points) { // Construct an array with the correct coordinate packing for OpenGL. int n = static_cast(points->GetNumberOfPoints()); // If the points are of type float then call OpenGL directly float* f = vtkArrayDownCast(points->GetData())->GetPointer(0); this->DrawQuadStrip(f, n); } //------------------------------------------------------------------------------ void vtkContext2D::DrawQuadStrip(float* points, int n) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } // Draw the filled area of the polygon. this->Device->DrawQuadStrip(points, n); } //------------------------------------------------------------------------------ void vtkContext2D::DrawPolygon(float* x, float* y, int n) { // Copy the points into an array and draw it. float* p = new float[2 * n]; for (int i = 0; i < n; ++i) { p[2 * i] = x[i]; p[2 * i + 1] = y[i]; } this->DrawPolygon(&p[0], n); delete[] p; } //------------------------------------------------------------------------------ void vtkContext2D::DrawPolygon(vtkPoints2D* points) { // Construct an array with the correct coordinate packing for OpenGL. int n = static_cast(points->GetNumberOfPoints()); // If the points are of type float then call OpenGL directly float* f = vtkArrayDownCast(points->GetData())->GetPointer(0); this->DrawPolygon(f, n); } //------------------------------------------------------------------------------ void vtkContext2D::DrawPolygon(float* points, int n) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } // Draw the filled area of the polygon. this->Device->DrawPolygon(points, n); // Draw the outline now. this->Device->DrawPoly(points, n); float closeLine[] = { points[0], points[1], points[2 * n - 2], points[2 * n - 1] }; this->Device->DrawPoly(&closeLine[0], 2); } //------------------------------------------------------------------------------ void vtkContext2D::DrawPolygon(float* x, float* y, int n, unsigned char* color, int nc_comps) { // Copy the points into an array and draw it. float* p = new float[2 * n]; for (int i = 0; i < n; ++i) { p[2 * i] = x[i]; p[2 * i + 1] = y[i]; } this->DrawPolygon(&p[0], n, color, nc_comps); delete[] p; } //------------------------------------------------------------------------------ void vtkContext2D::DrawPolygon(vtkPoints2D* points, unsigned char* color, int nc_comps) { // Construct an array with the correct coordinate packing for OpenGL. int n = static_cast(points->GetNumberOfPoints()); // If the points are of type float then call OpenGL directly float* f = vtkArrayDownCast(points->GetData())->GetPointer(0); this->DrawPolygon(f, n, color, nc_comps); } //------------------------------------------------------------------------------ void vtkContext2D::DrawPolygon(float* points, int n, unsigned char* color, int nc_comps) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } // Draw the filled area of the polygon. this->Device->DrawColoredPolygon(points, n, color, nc_comps); } //------------------------------------------------------------------------------ void vtkContext2D::DrawEllipse(float x, float y, float rx, float ry) { assert("pre: positive_rx" && rx >= 0); assert("pre: positive_ry" && ry >= 0); this->DrawEllipticArc(x, y, rx, ry, 0.0, 360.0); } //------------------------------------------------------------------------------ void vtkContext2D::DrawWedge( float x, float y, float outRadius, float inRadius, float startAngle, float stopAngle) { assert("pre: positive_outRadius" && outRadius >= 0.0f); assert("pre: positive_inRadius" && inRadius >= 0.0f); assert("pre: ordered_radii" && inRadius <= outRadius); this->DrawEllipseWedge(x, y, outRadius, outRadius, inRadius, inRadius, startAngle, stopAngle); } //------------------------------------------------------------------------------ void vtkContext2D::DrawEllipseWedge(float x, float y, float outRx, float outRy, float inRx, float inRy, float startAngle, float stopAngle) { assert("pre: positive_outRx" && outRx >= 0.0f); assert("pre: positive_outRy" && outRy >= 0.0f); assert("pre: positive_inRx" && inRx >= 0.0f); assert("pre: positive_inRy" && inRy >= 0.0f); assert("pre: ordered_rx" && inRx <= outRx); assert("pre: ordered_ry" && inRy <= outRy); if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } // don't tessellate here. The device context knows what to do with an // arc. An OpenGL device context will tessellate but and SVG context with // just generate an arc. this->Device->DrawEllipseWedge(x, y, outRx, outRy, inRx, inRy, startAngle, stopAngle); } //------------------------------------------------------------------------------ void vtkContext2D::DrawArc(float x, float y, float r, float startAngle, float stopAngle) { assert("pre: positive_radius" && r >= 0); this->DrawEllipticArc(x, y, r, r, startAngle, stopAngle); } //------------------------------------------------------------------------------ void vtkContext2D::DrawEllipticArc( float x, float y, float rX, float rY, float startAngle, float stopAngle) { assert("pre: positive_rX" && rX >= 0); assert("pre: positive_rY" && rY >= 0); if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } // don't tessellate here. The device context knows what to do with an // arc. An OpenGL device context will tessellate but and SVG context with // just generate an arc. this->Device->DrawEllipticArc(x, y, rX, rY, startAngle, stopAngle); } //------------------------------------------------------------------------------ void vtkContext2D::DrawStringRect(vtkPoints2D* rect, const vtkStdString& string) { vtkVector2f p = this->CalculateTextPosition(rect); this->DrawString(p.GetX(), p.GetY(), string); } //------------------------------------------------------------------------------ void vtkContext2D::DrawStringRect(vtkPoints2D* rect, const char* string) { this->DrawStringRect(rect, vtkStdString(string)); } //------------------------------------------------------------------------------ void vtkContext2D::DrawStringRect(const float rect[4], const vtkStdString& string) { vtkVector2f p = this->CalculateTextPosition(rect); this->DrawString(p.GetX(), p.GetY(), string); } //------------------------------------------------------------------------------ void vtkContext2D::DrawStringRect(const float rect[4], const char* string) { this->DrawStringRect(rect, vtkStdString(string)); } //------------------------------------------------------------------------------ void vtkContext2D::DrawString(vtkPoints2D* point, const vtkStdString& string) { float* f = vtkArrayDownCast(point->GetData())->GetPointer(0); this->DrawString(f[0], f[1], string); } //------------------------------------------------------------------------------ void vtkContext2D::DrawString(float x, float y, const vtkStdString& string) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } if (string.empty()) { return; } float f[] = { x, y }; this->Device->DrawString(f, string); } //------------------------------------------------------------------------------ void vtkContext2D::DrawString(vtkPoints2D* point, const char* string) { float* f = vtkArrayDownCast(point->GetData())->GetPointer(0); this->DrawString(f[0], f[1], vtkStdString(string)); } //------------------------------------------------------------------------------ void vtkContext2D::DrawString(float x, float y, const char* string) { this->DrawString(x, y, vtkStdString(string)); } //------------------------------------------------------------------------------ void vtkContext2D::ComputeStringBounds(const vtkStdString& string, vtkPoints2D* bounds) { bounds->SetNumberOfPoints(2); float* f = vtkArrayDownCast(bounds->GetData())->GetPointer(0); this->ComputeStringBounds(string, f); } //------------------------------------------------------------------------------ void vtkContext2D::ComputeStringBounds(const vtkStdString& string, float bounds[4]) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } this->Device->ComputeStringBounds(string, bounds); } //------------------------------------------------------------------------------ void vtkContext2D::ComputeStringBounds(const char* string, vtkPoints2D* bounds) { this->ComputeStringBounds(vtkStdString(string), bounds); } //------------------------------------------------------------------------------ void vtkContext2D::ComputeStringBounds(const char* string, float bounds[4]) { this->ComputeStringBounds(vtkStdString(string), bounds); } //------------------------------------------------------------------------------ void vtkContext2D::ComputeJustifiedStringBounds(const char* string, float bounds[4]) { this->Device->ComputeJustifiedStringBounds(string, bounds); } //------------------------------------------------------------------------------ int vtkContext2D::ComputeFontSizeForBoundedString( const vtkStdString& string, float width, float height) { double orientation = this->GetTextProp()->GetOrientation(); this->GetTextProp()->SetOrientation(0.0); float stringBounds[4]; int currentFontSize = this->GetTextProp()->GetFontSize(); this->ComputeStringBounds(string, stringBounds); // font size is too big if (stringBounds[2] > width || stringBounds[3] > height) { while (stringBounds[2] > width || stringBounds[3] > height) { --currentFontSize; this->GetTextProp()->SetFontSize(currentFontSize); this->ComputeStringBounds(string, stringBounds); if (currentFontSize < 0) { this->GetTextProp()->SetFontSize(0); return 0; } } } // font size is too small else { while (stringBounds[2] < width && stringBounds[3] < height) { ++currentFontSize; this->GetTextProp()->SetFontSize(currentFontSize); this->ComputeStringBounds(string, stringBounds); } --currentFontSize; this->GetTextProp()->SetFontSize(currentFontSize); } this->GetTextProp()->SetOrientation(orientation); return currentFontSize; } //------------------------------------------------------------------------------ void vtkContext2D::DrawMathTextString(vtkPoints2D* point, const vtkStdString& string) { float* f = vtkArrayDownCast(point->GetData())->GetPointer(0); this->DrawMathTextString(f[0], f[1], string); } //------------------------------------------------------------------------------ void vtkContext2D::DrawMathTextString(float x, float y, const vtkStdString& string) { if (!this->Device) { vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D."); return; } if (string.empty()) { return; } float f[] = { x, y }; this->Device->DrawMathTextString(f, string); } //------------------------------------------------------------------------------ void vtkContext2D::DrawMathTextString(vtkPoints2D* point, const char* string) { float* f = vtkArrayDownCast(point->GetData())->GetPointer(0); this->DrawMathTextString(f[0], f[1], vtkStdString(string)); } //------------------------------------------------------------------------------ void vtkContext2D::DrawMathTextString(float x, float y, const char* string) { this->DrawMathTextString(x, y, vtkStdString(string)); } //------------------------------------------------------------------------------ void vtkContext2D::DrawMathTextString( vtkPoints2D* point, const vtkStdString& string, const vtkStdString& fallback) { if (this->Device->MathTextIsSupported()) { this->DrawMathTextString(point, string); } else { this->DrawString(point, fallback); } } //------------------------------------------------------------------------------ void vtkContext2D::DrawMathTextString( float x, float y, const vtkStdString& string, const vtkStdString& fallback) { if (this->Device->MathTextIsSupported()) { this->DrawMathTextString(x, y, string); } else { this->DrawString(x, y, fallback); } } //------------------------------------------------------------------------------ void vtkContext2D::DrawMathTextString(vtkPoints2D* point, const char* string, const char* fallback) { if (this->Device->MathTextIsSupported()) { this->DrawMathTextString(point, string); } else { this->DrawString(point, fallback); } } //------------------------------------------------------------------------------ void vtkContext2D::DrawMathTextString(float x, float y, const char* string, const char* fallback) { if (this->Device->MathTextIsSupported()) { this->DrawMathTextString(x, y, string); } else { this->DrawString(x, y, fallback); } } //------------------------------------------------------------------------------ bool vtkContext2D::MathTextIsSupported() { return this->Device->MathTextIsSupported(); } //------------------------------------------------------------------------------ void vtkContext2D::DrawImage(float x, float y, vtkImageData* image) { float p[] = { x, y }; this->Device->DrawImage(&p[0], 1.0, image); } //------------------------------------------------------------------------------ void vtkContext2D::DrawImage(float x, float y, float scale, vtkImageData* image) { float p[] = { x, y }; this->Device->DrawImage(&p[0], scale, image); } //------------------------------------------------------------------------------ void vtkContext2D::DrawImage(const vtkRectf& pos, vtkImageData* image) { this->Device->DrawImage(pos, image); } //------------------------------------------------------------------------------ void vtkContext2D::DrawPolyData( float x, float y, vtkPolyData* polyData, vtkUnsignedCharArray* colors, int scalarMode) { float p[] = { x, y }; this->Device->DrawPolyData(&p[0], 1.0, polyData, colors, scalarMode); } //------------------------------------------------------------------------------ void vtkContext2D::ApplyPen(vtkPen* pen) { this->Device->ApplyPen(pen); } //------------------------------------------------------------------------------ vtkPen* vtkContext2D::GetPen() { if (this->Device) { return this->Device->GetPen(); } return nullptr; } //------------------------------------------------------------------------------ void vtkContext2D::ApplyBrush(vtkBrush* brush) { this->Device->ApplyBrush(brush); } //------------------------------------------------------------------------------ vtkBrush* vtkContext2D::GetBrush() { if (this->Device) { return this->Device->GetBrush(); } return nullptr; } //------------------------------------------------------------------------------ void vtkContext2D::ApplyTextProp(vtkTextProperty* prop) { this->Device->ApplyTextProp(prop); } //------------------------------------------------------------------------------ vtkTextProperty* vtkContext2D::GetTextProp() { if (this->Device) { return this->Device->GetTextProp(); } return nullptr; } //------------------------------------------------------------------------------ void vtkContext2D::SetTransform(vtkTransform2D* transform) { if (transform) { this->Device->SetMatrix(transform->GetMatrix()); } } //------------------------------------------------------------------------------ vtkTransform2D* vtkContext2D::GetTransform() { if (this->Device && this->Transform) { this->Device->GetMatrix(this->Transform->GetMatrix()); return this->Transform; } return nullptr; } //------------------------------------------------------------------------------ void vtkContext2D::AppendTransform(vtkTransform2D* transform) { if (!transform) { return; } this->Device->MultiplyMatrix(transform->GetMatrix()); } //------------------------------------------------------------------------------ void vtkContext2D::PushMatrix() { this->Device->PushMatrix(); } //------------------------------------------------------------------------------ void vtkContext2D::PopMatrix() { this->Device->PopMatrix(); } //------------------------------------------------------------------------------ void vtkContext2D::ApplyId(vtkIdType id) { assert("pre: zero_reserved_for_background" && id > 0); assert("pre: 24bit_limited" && id < 16777216); unsigned char rgba[4]; // r most significant bits (16-23). // g (8-15) // b less significant bits (0-7). rgba[0] = static_cast((id & 0xff0000) >> 16); rgba[1] = static_cast((id & 0xff00) >> 8); rgba[2] = static_cast(id & 0xff); rgba[3] = 1; // not used (because the colorbuffer in the default framebuffer // may not have an alpha channel) assert("check: valid_conversion" && static_cast((static_cast(rgba[0]) << 16) | (static_cast(rgba[1]) << 8) | static_cast(rgba[2])) == id); this->Device->SetColor4(rgba); } void vtkContext2D::SetContext3D(vtkContext3D* context) { this->Context3D = context; } //------------------------------------------------------------------------------ vtkVector2f vtkContext2D::CalculateTextPosition(vtkPoints2D* rect) { if (rect->GetNumberOfPoints() < 2) { return vtkVector2f(0, 0); } float* f = vtkArrayDownCast(rect->GetData())->GetPointer(0); return this->CalculateTextPosition(f); } //------------------------------------------------------------------------------ vtkVector2f vtkContext2D::CalculateTextPosition(const float rect[4]) { // Draw the text at the appropriate point inside the rect for the alignment // specified. This is a convenience when an area of the screen should have // text drawn that is aligned to the entire area. vtkVector2f p(0, 0); if (this->Device->GetTextProp()->GetJustification() == VTK_TEXT_LEFT) { p.SetX(rect[0]); } else if (this->Device->GetTextProp()->GetJustification() == VTK_TEXT_CENTERED) { p.SetX(rect[0] + 0.5f * rect[2]); } else { p.SetX(rect[0] + rect[2]); } if (this->Device->GetTextProp()->GetVerticalJustification() == VTK_TEXT_BOTTOM) { p.SetY(rect[1]); } else if (this->Device->GetTextProp()->GetVerticalJustification() == VTK_TEXT_CENTERED) { p.SetY(rect[1] + 0.5f * rect[3]); } else { p.SetY(rect[1] + rect[3]); } return p; } //------------------------------------------------------------------------------ vtkContext2D::vtkContext2D() : Context3D(nullptr) { this->Device = nullptr; this->Transform = vtkTransform2D::New(); this->BufferId = nullptr; } //------------------------------------------------------------------------------ vtkContext2D::~vtkContext2D() { if (this->Device) { this->Device->Delete(); } if (this->Transform) { this->Transform->Delete(); } } //------------------------------------------------------------------------------ void vtkContext2D::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Context Device: "; if (this->Device) { os << endl; this->Device->PrintSelf(os, indent.GetNextIndent()); } else { os << "(none)" << endl; } }