721 lines
28 KiB
C++
721 lines
28 KiB
C++
// Copyright (c) 1996-2001 by Autodesk, Inc.
|
|
//
|
|
// By using this code, you are agreeing to the terms and conditions of
|
|
// the License Agreement included in the documentation for this code.
|
|
//
|
|
// AUTODESK MAKES NO WARRANTIES, EXPRESS OR IMPLIED, AS TO THE CORRECTNESS
|
|
// OF THIS CODE OR ANY DERIVATIVE WORKS WHICH INCORPORATE IT. AUTODESK
|
|
// PROVIDES THE CODE ON AN "AS-IS" BASIS AND EXPLICITLY DISCLAIMS ANY
|
|
// LIABILITY, INCLUDING CONSEQUENTIAL AND INCIDENTAL DAMAGES FOR ERRORS,
|
|
// OMISSIONS, AND OTHER PROBLEMS IN THE CODE.
|
|
//
|
|
// Use, duplication, or disclosure by the U.S. Government is subject to
|
|
// restrictions set forth in FAR 52.227-19 (Commercial Computer Software
|
|
// Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) (Rights in Technical
|
|
// Data and Computer Software), as applicable.
|
|
//
|
|
// $Header: /NewRoot/DWF Toolkit/v6/develop/global/src/dwf/whiptk/ellipse.cpp 1 9/12/04 8:52p Evansg $
|
|
|
|
#include "whiptk/pch.h"
|
|
#include "whiptk/wversion.h"
|
|
|
|
const double PI = 3.14159265358979323846;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
WT_Object::WT_ID WT_Filled_Ellipse::object_id() const
|
|
{
|
|
return Filled_Ellipse_ID;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
WT_Object::WT_ID WT_Outline_Ellipse::object_id() const
|
|
{
|
|
return Outline_Ellipse_ID;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
#if DESIRED_CODE(WHIP_OUTPUT)
|
|
WT_Result WT_Filled_Ellipse::serialize(WT_File & file) const
|
|
{
|
|
return WT_Ellipse::serialize (file, WD_True);
|
|
}
|
|
#else
|
|
WT_Result WT_Filled_Ellipse::serialize(WT_File &) const
|
|
{
|
|
return WT_Result::Success;
|
|
}
|
|
#endif // DESIRED_CODE()
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
#if DESIRED_CODE(WHIP_OUTPUT)
|
|
WT_Result WT_Outline_Ellipse::serialize(WT_File & file) const
|
|
{
|
|
return WT_Ellipse::serialize (file, WD_False);
|
|
}
|
|
#else
|
|
WT_Result WT_Outline_Ellipse::serialize(WT_File &) const
|
|
{
|
|
return WT_Result::Success;
|
|
}
|
|
#endif // DESIRED_CODE()
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
#if DESIRED_CODE(WHIP_OUTPUT)
|
|
WT_Result WT_Ellipse::serialize(WT_File & file, WT_Boolean filled) const
|
|
{
|
|
WD_CHECK (file.dump_delayed_drawable());
|
|
|
|
// TODO: Check rendition incarnation
|
|
|
|
// Attributes that Filled_Ellipses care about:
|
|
// color, line weight, line cap, line join,
|
|
// line pattern, fill mode, visibility, URL
|
|
// layer
|
|
|
|
WT_Integer32 parts_to_sync = WT_Rendition::Color_Bit |
|
|
// WT_Rendition::Color_Map_Bit |
|
|
// WT_Rendition::Fill_Bit |
|
|
WT_Rendition::Fill_Pattern_Bit |
|
|
WT_Rendition::Merge_Control_Bit |
|
|
WT_Rendition::BlockRef_Bit |
|
|
WT_Rendition::Visibility_Bit |
|
|
// WT_Rendition::Marker_Size_Bit |
|
|
// WT_Rendition::Marker_Symbol_Bit |
|
|
WT_Rendition::URL_Bit |
|
|
WT_Rendition::Viewport_Bit |
|
|
WT_Rendition::Layer_Bit |
|
|
WT_Rendition::Object_Node_Bit;
|
|
|
|
|
|
if (filled)
|
|
{
|
|
if (!file.rendition().fill().fill())
|
|
{
|
|
file.desired_rendition().fill() = WD_True;
|
|
parts_to_sync |= WT_Rendition::Fill_Bit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
parts_to_sync |= WT_Rendition::Line_Weight_Bit |
|
|
WT_Rendition::Pen_Pattern_Bit |
|
|
WT_Rendition::Line_Pattern_Bit |
|
|
WT_Rendition::Dash_Pattern_Bit |
|
|
WT_Rendition::Line_Style_Bit;
|
|
|
|
if (file.rendition().fill().fill())
|
|
{
|
|
file.desired_rendition().fill() = WD_False;
|
|
parts_to_sync |= WT_Rendition::Fill_Bit;
|
|
}
|
|
}
|
|
|
|
WD_CHECK (file.desired_rendition().sync(file, parts_to_sync));
|
|
|
|
if (file.heuristics().apply_transform())
|
|
((WT_Filled_Ellipse *)this)->transform(file.heuristics().transform()); // Cast "this" from const to alterable
|
|
|
|
if (file.heuristics().allow_binary_data())
|
|
{
|
|
WT_Logical_Point relpos = file.update_current_point(m_position);
|
|
|
|
// Binary output
|
|
if (m_major != m_minor)
|
|
{
|
|
// output as Ellipse
|
|
WD_CHECK (file.write ((WT_Byte)'e'));
|
|
WD_CHECK (file.write (1, &relpos));
|
|
WD_CHECK (file.write (m_major));
|
|
WD_CHECK (file.write (m_minor));
|
|
WD_CHECK (file.write (m_start));
|
|
WD_CHECK (file.write ((WT_Unsigned_Integer16)(m_end & 0xFFFF)));
|
|
return file.write (m_tilt);
|
|
}
|
|
else if (m_start != m_end)
|
|
{
|
|
// Output a 32 bit partial circle
|
|
|
|
// merge any ellipse tilt into the circle angles
|
|
long start = ((long)m_start + (long)m_tilt) & 0x0000FFFF;
|
|
long end = ((long)m_end + (long)m_tilt) & 0x0000FFFF;
|
|
|
|
WD_CHECK (file.write ((WT_Byte)0x92));
|
|
WD_CHECK (file.write (1, &relpos));
|
|
WD_CHECK (file.write (m_major));
|
|
WD_CHECK (file.write ((WT_Unsigned_Integer16)start));
|
|
return file.write ((WT_Unsigned_Integer16)end);
|
|
}
|
|
else if (WD_fits_in_short (relpos.m_x) && WD_fits_in_short (relpos.m_y) &&
|
|
WD_fits_in_short (m_major))
|
|
{
|
|
// Output a 16 bit relative full circle
|
|
WT_Logical_Point_16 tmp_point;
|
|
tmp_point = relpos;
|
|
|
|
WD_CHECK (file.write ((WT_Byte)0x12));
|
|
WD_CHECK (file.write (1, &tmp_point));
|
|
return file.write ((WT_Integer16)m_major);
|
|
}
|
|
else
|
|
{
|
|
// Output a 32 bit relative full circle
|
|
WD_CHECK (file.write ((WT_Byte)'r'));
|
|
WD_CHECK (file.write (1, &relpos));
|
|
return file.write (m_major);
|
|
}
|
|
} // allow binary data
|
|
else
|
|
{
|
|
// ASCII only output -----------------------
|
|
WD_CHECK (file.write_geom_tab_level());
|
|
|
|
if (m_major != m_minor)
|
|
{
|
|
// output as Ellipse in ASCII
|
|
|
|
if ((m_start != m_end) || m_tilt)
|
|
{
|
|
// Full description of an ellipse
|
|
WD_CHECK (file.write ("(Ellipse "));
|
|
WD_CHECK (file.write_ascii (m_position));
|
|
WD_CHECK (file.write ((WT_Byte) ' '));
|
|
|
|
WD_CHECK (file.write_ascii (m_major));
|
|
WD_CHECK (file.write ((WT_Byte) ','));
|
|
WD_CHECK (file.write_ascii (m_minor));
|
|
WD_CHECK (file.write ((WT_Byte) ' '));
|
|
|
|
WD_CHECK (file.write_ascii (m_start));
|
|
WD_CHECK (file.write ((WT_Byte) ','));
|
|
WD_CHECK (file.write_ascii (m_end));
|
|
WD_CHECK (file.write ((WT_Byte) ' '));
|
|
|
|
WD_CHECK (file.write_ascii (m_tilt));
|
|
|
|
return file.write((WT_Byte) ')');
|
|
}
|
|
else
|
|
{
|
|
// Basic description of an ellipse
|
|
WD_CHECK (file.write ("E "));
|
|
WD_CHECK (file.write_ascii (1, &m_position));
|
|
WD_CHECK (file.write ((WT_Byte) ' '));
|
|
|
|
WD_CHECK (file.write_ascii (m_major));
|
|
WD_CHECK (file.write ((WT_Byte) ','));
|
|
return file.write_ascii (m_minor);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// merge any ellipse tilt into the circle angles
|
|
long start = ((long)m_start + (long)m_tilt) & 0x0000FFFF;
|
|
long end = ((long)m_end + (long)m_tilt) & 0x0000FFFF;
|
|
|
|
// Output a circle in ASCII
|
|
if (start != end)
|
|
{
|
|
// Full description of the circle/arc
|
|
WD_CHECK (file.write ("(Circle "));
|
|
WD_CHECK (file.write_ascii (m_position));
|
|
WD_CHECK (file.write ((WT_Byte) ' '));
|
|
WD_CHECK (file.write_ascii (m_major));
|
|
|
|
WD_CHECK (file.write ((WT_Byte) ' '));
|
|
WD_CHECK (file.write_ascii (start));
|
|
WD_CHECK (file.write ((WT_Byte) ','));
|
|
WD_CHECK (file.write_ascii (end));
|
|
|
|
return file.write((WT_Byte) ')');
|
|
}
|
|
else
|
|
{
|
|
// Basic circle
|
|
WD_CHECK (file.write ("R "));
|
|
WD_CHECK (file.write_ascii (m_position));
|
|
WD_CHECK (file.write ((WT_Byte) ' '));
|
|
return file.write_ascii (m_major);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
WT_Result WT_Ellipse::serialize(WT_File &, WT_Boolean) const
|
|
{
|
|
return WT_Result::Success;
|
|
}
|
|
#endif // DESIRED_CODE()
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
bool containsAngle(double angle, double angleStart, double angleEnd)
|
|
{
|
|
// get the orientation
|
|
bool isCCW = angleStart < angleEnd;
|
|
|
|
// put the supplied parameter value on the extent side of the start angle
|
|
if (isCCW)
|
|
{
|
|
while (angle < angleStart)
|
|
angle += 2.0*PI;
|
|
while (angle- 2.0*PI > angleStart)
|
|
angle -= 2.0*PI;
|
|
}
|
|
else
|
|
{
|
|
while (angle > angleStart)
|
|
angle -= 2.0*PI;
|
|
while (angle+2.0*PI < angleStart)
|
|
angle += 2.0*PI;
|
|
}
|
|
|
|
// do the range check
|
|
if (isCCW)
|
|
{
|
|
// normal orientation
|
|
if (angle >= angleStart && angle <= angleEnd)
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
// reversed orientation
|
|
if (angle >= angleEnd && angle <= angleStart)
|
|
return true;
|
|
}
|
|
|
|
// not in range
|
|
return false;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void WT_Ellipse::update_bounds(WT_File * file)
|
|
{
|
|
//Bounds algorithm lifted and ported from Kona
|
|
|
|
double maj = major();
|
|
double min = minor();
|
|
|
|
double ang = tilt_radian();
|
|
double csa = cos(ang);
|
|
double sna = sin(ang);
|
|
|
|
double ax = maj * csa;
|
|
double bx = min * sna;
|
|
double ay = maj * sna;
|
|
double by = min * csa;
|
|
double xmax = sqrt(ax*ax + bx*bx);
|
|
double ymax = sqrt(ay*ay + by*by);
|
|
|
|
double asValue = start_radian();;
|
|
double css = cos(asValue);
|
|
double sns = sin(asValue);
|
|
double xs = ax*css - bx*sns;
|
|
double ys = ay*css + by*sns;
|
|
|
|
double ae = end_radian();
|
|
double cse = cos(ae);
|
|
double sne = sin(ae);
|
|
double xe = ax*cse - bx*sne;
|
|
double ye = ay*cse + by*sne;
|
|
|
|
WT_Drawable::update_bounds(WT_Logical_Point((int)xs+m_position.m_x,(int)ys+m_position.m_y), file);
|
|
WT_Drawable::update_bounds(WT_Logical_Point(((int)xs)+m_position.m_x+1,((int)ys)+m_position.m_y+1), file);
|
|
WT_Drawable::update_bounds(WT_Logical_Point((int)xe+m_position.m_x,(int)ye+m_position.m_y), file);
|
|
WT_Drawable::update_bounds(WT_Logical_Point(((int)xe)+m_position.m_x+1,((int)ye)+m_position.m_y+1), file);
|
|
|
|
double asnorm = atan2(sns, css);
|
|
double aenorm = ae + (asnorm - asValue);
|
|
|
|
double txmax = atan2(-min*sna, maj*csa);
|
|
double txmin = txmax - PI;
|
|
if (txmin <= -PI)
|
|
txmin += 2.0*PI;
|
|
|
|
if (containsAngle(txmax, asnorm, aenorm))
|
|
WT_Drawable::update_bounds(WT_Logical_Point(((int)xmax)+m_position.m_x+1, ((int)ys)+m_position.m_y+1), file);
|
|
if (containsAngle(txmin, asnorm, aenorm))
|
|
WT_Drawable::update_bounds(WT_Logical_Point((int)-xmax+m_position.m_x, (int)ys+m_position.m_y), file);
|
|
|
|
double tymax = atan2(min*csa, maj*sna);
|
|
double tymin = tymax - PI;
|
|
if (tymin <= -PI)
|
|
tymin += 2.0*PI;
|
|
|
|
if (containsAngle(tymax, asnorm, aenorm))
|
|
WT_Drawable::update_bounds(WT_Logical_Point(((int)xs)+m_position.m_x+1, ((int)ymax)+m_position.m_y+1), file);
|
|
if (containsAngle(tymin, asnorm, aenorm))
|
|
WT_Drawable::update_bounds(WT_Logical_Point((int)xs+m_position.m_x, (int)-ymax+m_position.m_y), file);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
WT_Result WT_Ellipse::materialize(WT_Opcode const & opcode, WT_File & file)
|
|
{
|
|
WT_Logical_Point tmp_point;
|
|
|
|
switch (opcode.type())
|
|
{
|
|
case WT_Opcode::Single_Byte:
|
|
{
|
|
switch (opcode.token()[0])
|
|
{
|
|
case 'E':
|
|
{
|
|
// Ellipse, single-byte full ASCII
|
|
switch (m_stage)
|
|
{
|
|
case Get_Position: WD_CHECK (file.read_ascii (m_position));
|
|
m_stage = Get_Major;
|
|
case Get_Major: WD_CHECK (file.read_ascii (tmp_point));
|
|
m_major = tmp_point.m_x;
|
|
m_minor = tmp_point.m_y;
|
|
m_stage = Completed;
|
|
break;
|
|
default:
|
|
return WT_Result::Internal_Error;
|
|
}
|
|
|
|
// Note: for full ASCII we *don't* de-relativize since we already have absolute coords.
|
|
} break;
|
|
case 'e':
|
|
{
|
|
// Ellipse, binary, long relative coordinates
|
|
switch (m_stage)
|
|
{
|
|
case Get_Position: WD_CHECK (file.read (1, &m_position));
|
|
m_stage = Get_Major;
|
|
case Get_Major: WD_CHECK (file.read (m_major));
|
|
m_stage = Get_Minor;
|
|
case Get_Minor: WD_CHECK (file.read (m_minor));
|
|
m_stage = Get_Start;
|
|
case Get_Start: WD_CHECK (file.read (m_start));
|
|
m_stage = Get_End;
|
|
case Get_End: WT_Unsigned_Integer16 tmp;
|
|
WD_CHECK (file.read (tmp));
|
|
m_end = tmp;
|
|
m_stage = Get_Tilt;
|
|
case Get_Tilt: WD_CHECK (file.read (m_tilt));
|
|
m_stage = Completed;
|
|
break;
|
|
default:
|
|
return WT_Result::Internal_Error;
|
|
}
|
|
|
|
// convert from relative to absolute, transform if appropriate
|
|
m_position = file.de_update_current_point(m_position);
|
|
} break;
|
|
case 'R':
|
|
{
|
|
// Basic Circle, Ascii
|
|
switch (m_stage)
|
|
{
|
|
case Get_Position: WD_CHECK (file.read_ascii (m_position));
|
|
m_stage = Get_Major;
|
|
case Get_Major: WD_CHECK (file.read_ascii (m_major));
|
|
m_minor = m_major;
|
|
m_start = 0;
|
|
m_end = 0;
|
|
m_tilt = 0;
|
|
m_stage = Completed;
|
|
break;
|
|
default:
|
|
return WT_Result::Internal_Error;
|
|
}
|
|
// Note: for full ASCII we *don't* de-relativize since we already have absolute coords.
|
|
} break;
|
|
case 'r':
|
|
{
|
|
// Full Circle, long relative coordinates
|
|
switch (m_stage)
|
|
{
|
|
case Get_Position: WD_CHECK (file.read (1, &m_position));
|
|
m_stage = Get_Major;
|
|
case Get_Major: WD_CHECK (file.read (m_major));
|
|
m_minor = m_major;
|
|
m_start = 0;
|
|
m_end = 0x00010000;
|
|
m_tilt = 0;
|
|
m_stage = Completed;
|
|
break;
|
|
default:
|
|
return WT_Result::Internal_Error;
|
|
}
|
|
|
|
// convert from relative to absolute, transform if appropriate
|
|
m_position = file.de_update_current_point(m_position);
|
|
} break;
|
|
case 0x12: // Ctrl-R
|
|
{
|
|
// Full Circle, short relative coordinates
|
|
WT_Logical_Point_16 position;
|
|
WT_Unsigned_Integer16 radius;
|
|
|
|
switch (m_stage)
|
|
{
|
|
case Get_Position: WD_CHECK (file.read (1, &position));
|
|
m_position = position;
|
|
m_stage = Get_Major;
|
|
case Get_Major: WD_CHECK (file.read (radius));
|
|
m_major = m_minor = radius;
|
|
m_start = 0;
|
|
m_end = 0x00010000;
|
|
m_tilt = 0;
|
|
m_stage = Completed;
|
|
break;
|
|
default:
|
|
return WT_Result::Internal_Error;
|
|
}
|
|
|
|
// convert from relative to absolute, transform if appropriate
|
|
m_position = file.de_update_current_point(m_position);
|
|
} break;
|
|
case 0x92: // X-Ctrl-R
|
|
{
|
|
// Partial or Full Circle, long relative coordinates, short angles
|
|
switch (m_stage)
|
|
{
|
|
case Get_Position: WD_CHECK (file.read (1, &m_position));
|
|
m_stage = Get_Major;
|
|
case Get_Major: WD_CHECK (file.read (m_major));
|
|
m_minor = m_major;
|
|
m_stage = Get_Start;
|
|
case Get_Start: WD_CHECK (file.read (m_start));
|
|
m_stage = Get_End;
|
|
case Get_End: WT_Unsigned_Integer16 tmp;
|
|
WD_CHECK (file.read (tmp));
|
|
m_end = tmp;
|
|
m_stage = Completed;
|
|
break;
|
|
default:
|
|
return WT_Result::Internal_Error;
|
|
}
|
|
|
|
// convert from relative to absolute, transform if appropriate
|
|
m_position = file.de_update_current_point(m_position);
|
|
} break;
|
|
default:
|
|
return WT_Result::Opcode_Not_Valid_For_This_Object;
|
|
// break;
|
|
} // switch
|
|
} break;
|
|
case WT_Opcode::Extended_ASCII:
|
|
{
|
|
if (!strcmp((char const *) opcode.token(), "(Circle"))
|
|
{
|
|
// Partial or Full Circle, absolute coordinates, short angles
|
|
switch (m_stage)
|
|
{
|
|
case Get_Position: WD_CHECK (file.read_ascii (m_position));
|
|
m_stage = Get_Major;
|
|
case Get_Major: WD_CHECK (file.read_ascii (m_major));
|
|
m_minor = m_major;
|
|
m_stage = Get_Start;
|
|
case Get_Start: WD_CHECK (file.read_ascii (tmp_point));
|
|
if (tmp_point.m_x < 0 || tmp_point.m_y < 0)
|
|
return WT_Result::Corrupt_File_Error;
|
|
m_start = (WT_Unsigned_Integer16)(tmp_point.m_x & 0XFFFF);
|
|
m_end = tmp_point.m_y & 0x0001FFFF;
|
|
m_stage = Get_Close_Paren;
|
|
case Get_Close_Paren:
|
|
WD_CHECK (opcode.skip_past_matching_paren(file));
|
|
m_stage = Completed;
|
|
break;
|
|
default:
|
|
return WT_Result::Internal_Error;
|
|
}
|
|
// Note: for full ASCII we *don't* de-relativize since we already have absolute coords.
|
|
}
|
|
else if (!strcmp((char const *) opcode.token(), "(Ellipse"))
|
|
{
|
|
// Ellipse, single-byte full ASCII
|
|
|
|
switch (m_stage)
|
|
{
|
|
case Get_Position: WD_CHECK (file.read_ascii (m_position));
|
|
m_stage = Get_Major;
|
|
case Get_Major: WD_CHECK (file.read_ascii (tmp_point));
|
|
m_major = tmp_point.m_x;
|
|
m_minor = tmp_point.m_y;
|
|
m_stage = Get_Start;
|
|
case Get_Start: WD_CHECK (file.read_ascii (tmp_point));
|
|
if (tmp_point.m_x < 0 || tmp_point.m_y < 0)
|
|
return WT_Result::Corrupt_File_Error;
|
|
m_start = (WT_Unsigned_Integer16)(tmp_point.m_x & 0XFFFF);
|
|
m_end = tmp_point.m_y & 0x0001FFFF;
|
|
m_stage = Get_Tilt;
|
|
case Get_Tilt: WD_CHECK (file.read_ascii (m_tilt));
|
|
m_stage = Get_Close_Paren;
|
|
case Get_Close_Paren:
|
|
WD_CHECK (opcode.skip_past_matching_paren(file));
|
|
m_stage = Completed;
|
|
break;
|
|
default:
|
|
return WT_Result::Internal_Error;
|
|
}
|
|
// Note: for full ASCII we *don't* de-relativize since we already have absolute coords.
|
|
}
|
|
else
|
|
return WT_Result::Opcode_Not_Valid_For_This_Object;
|
|
} break;
|
|
case WT_Opcode::Extended_Binary:
|
|
default:
|
|
{
|
|
return WT_Result::Opcode_Not_Valid_For_This_Object;
|
|
} break;
|
|
} // switch
|
|
|
|
if (file.heuristics().apply_transform())
|
|
transform(file.heuristics().transform());
|
|
|
|
m_materialized = WD_True;
|
|
|
|
if (file.rendition().drawing_info().decimal_revision() <= WHIP20_DWF_FILE_VERSION)
|
|
{
|
|
// Note that in old versions, if m_start == m_end this is
|
|
// a null ellipse/circle that shouldn't be drawn. In this case
|
|
// we leave both m_start and m_end the same since Heidi knows not
|
|
// to draw such a case.
|
|
if (m_start == m_end)
|
|
return WT_Result::Success;
|
|
|
|
// In old versions, a complete circle was when m_end was one less than m_start.
|
|
// Adjust for the current definition which is that a complete circle is when
|
|
// they are the same value. (If you want a null circle, just don't put it
|
|
// in the DWF file, stupid!).
|
|
if (m_end < 0x00010000)
|
|
m_end++;
|
|
}
|
|
|
|
if (m_end <= m_start)
|
|
m_end += 0x00010000;
|
|
|
|
return WT_Result::Success;
|
|
}
|
|
|
|
WT_Result WT_Ellipse::skip_operand(WT_Opcode const & opcode, WT_File & file)
|
|
{
|
|
switch (opcode.type())
|
|
{
|
|
case WT_Opcode::Single_Byte:
|
|
{
|
|
switch (opcode.token()[0])
|
|
{
|
|
case 'E':
|
|
{
|
|
WT_Logical_Point tmp_pt;
|
|
WD_CHECK(file.read_ascii(tmp_pt));
|
|
WD_CHECK(file.read_ascii(tmp_pt));
|
|
} break;
|
|
case 'e':
|
|
{
|
|
// This is an ellipse, with 32-bit relative coords, 32-bit axes, 16-bit angles
|
|
file.skip(2 * sizeof(WT_Integer32) +
|
|
2 * sizeof(WT_Unsigned_Integer32) +
|
|
3 * sizeof(WT_Unsigned_Integer16));
|
|
} break;
|
|
case 'R':
|
|
{
|
|
WT_Integer32 tmp;
|
|
WT_Logical_Point tmp_pt;
|
|
WD_CHECK(file.read_ascii(tmp_pt));
|
|
WD_CHECK(file.read_ascii(tmp));
|
|
} break;
|
|
case 'r':
|
|
{
|
|
// This is a circle, with 32-bit relative coords, 32-bit radius
|
|
file.skip(2 * sizeof(WT_Integer32) +
|
|
sizeof(WT_Unsigned_Integer32));
|
|
} break;
|
|
case 0x12: // Ctrl-R
|
|
{
|
|
// This is a circle, with 16-bit relative coords, 16-bit radius
|
|
file.skip(2 * sizeof(WT_Integer16) +
|
|
sizeof(WT_Unsigned_Integer16));
|
|
} break;
|
|
case 0x92: // X-Ctrl-R
|
|
{
|
|
// This is a circle, with 32-bit relative coords, 32-bit radius, 16-bit angles
|
|
file.skip(2 * sizeof(WT_Integer32) +
|
|
sizeof(WT_Unsigned_Integer32) +
|
|
2 * sizeof(WT_Unsigned_Integer16));
|
|
} break;
|
|
default:
|
|
return WT_Result::Opcode_Not_Valid_For_This_Object;
|
|
// break;
|
|
} // switch
|
|
|
|
|
|
} break;
|
|
case WT_Opcode::Extended_ASCII:
|
|
WD_CHECK(opcode.skip_past_matching_paren(file));
|
|
break;
|
|
case WT_Opcode::Extended_Binary:
|
|
default:
|
|
{
|
|
return WT_Result::Opcode_Not_Valid_For_This_Object;
|
|
} break;
|
|
} // switch
|
|
|
|
return WT_Result::Success;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void WT_Ellipse::transform(WT_Transform const & transform)
|
|
{
|
|
if (!m_transformed)
|
|
{
|
|
// m_position.m_x = (WT_Integer32)((m_position.m_x + transform.m_translate.m_x) * transform.m_x_scale);
|
|
// m_position.m_y = (WT_Integer32)((m_position.m_y + transform.m_translate.m_y) * transform.m_y_scale);
|
|
|
|
// m_position.m_x = (WT_Integer32)((m_position.m_x * transform.m_x_scale) + transform.m_translate.m_x);
|
|
// m_position.m_y = (WT_Integer32)((m_position.m_y * transform.m_y_scale) + transform.m_translate.m_y);
|
|
|
|
WT_Logical_Point orig_pt(m_position);
|
|
|
|
m_position = orig_pt * transform; // we should use *=, but there seems to be a problem?
|
|
|
|
m_major = (WT_Unsigned_Integer32)(m_major * transform.m_x_scale);
|
|
m_minor = (WT_Unsigned_Integer32)(m_minor * transform.m_y_scale);
|
|
|
|
if (m_major < 0)
|
|
m_major = - m_major;
|
|
if (m_minor < 0)
|
|
m_minor = - m_minor;
|
|
|
|
m_tilt = (WT_Unsigned_Integer16)(
|
|
(WT_Unsigned_Integer16)
|
|
( (long)m_tilt +
|
|
(long)WD_90_DEGREES_AS_SHORT * ((double)transform.rotation() / 90)
|
|
) & 0x0000FFFF);
|
|
|
|
// TODO: note that we can simplify some ellipses by incorporating the tilt in and
|
|
// exchanging the major and minor axes or by rotating the start and end points.
|
|
|
|
m_transformed = WD_True;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
WT_Result WT_Filled_Ellipse::process(WT_File & file)
|
|
{
|
|
WD_Assert (file.filled_ellipse_action());
|
|
return (file.filled_ellipse_action())(*this, file);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
WT_Result WT_Filled_Ellipse::default_process(WT_Filled_Ellipse &, WT_File &)
|
|
{
|
|
return WT_Result::Success;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
WT_Result WT_Outline_Ellipse::process(WT_File & file)
|
|
{
|
|
WD_Assert (file.outline_ellipse_action());
|
|
return (file.outline_ellipse_action())(*this, file);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
WT_Result WT_Outline_Ellipse::default_process(WT_Outline_Ellipse &, WT_File &)
|
|
{
|
|
return WT_Result::Success;
|
|
}
|