SLNKDWF 2.11

svn path=/Slnkdwf/trunk/; revision=12487
This commit is contained in:
Jos Groot Lipman
2008-02-12 07:07:56 +00:00
parent b895b9cda8
commit 0b9083fc17
22 changed files with 2974 additions and 75 deletions

View File

@@ -94,3 +94,18 @@ STDMETHODIMP CAbout::get_VersionString(BSTR* pVal)
return S_OK;
}
STDMETHODIMP CAbout::get_usTimer(DOUBLE* pVal)
{
LARGE_INTEGER currTime;
LARGE_INTEGER frequency;
(*pVal)=0;
if (!QueryPerformanceFrequency(&frequency))
return S_OK;
if (!QueryPerformanceCounter(&currTime))
return S_OK;
(*pVal) = ((double)currTime.QuadPart)*1000000/frequency.QuadPart;
return S_OK;
}

View File

@@ -47,6 +47,7 @@ public:
STDMETHOD(get_VersionMajor)(LONG* pVal);
STDMETHOD(get_VersionMinor)(LONG* pVal);
STDMETHOD(get_VersionString)(BSTR* pVal);
STDMETHOD(get_usTimer)(DOUBLE* pVal);
};
OBJECT_ENTRY_AUTO(__uuidof(About), CAbout)

View File

@@ -39,7 +39,7 @@ void CSLNKContour::SetImpl(CSLNKContourImpl * pSLNKContour)
m_dwgCenter->put_DwgY(dwgPt.m_y);
};
STDMETHODIMP CSLNKContour::SetColor(ULONG rgb, BYTE Alpha /*=0*/)
STDMETHODIMP CSLNKContour::SetColor(ULONG rgb, BYTE Alpha /*=255*/)
{
int b=rgb%256;
int g=(rgb>>8)%256;

View File

@@ -48,7 +48,7 @@ interface IWhipFile : IDispatch{
[id(2), helpstring("method LoadStream")] HRESULT LoadStream([in] VARIANT EPlotStream);
[id(3), helpstring("method SaveAs")] HRESULT SaveAs([in] BSTR WhipPath);
[id(4), helpstring("method SetLabel")] HRESULT SetLabel([in] BSTR IdentLabel, [in] BSTR ExtraLabel);
[id(5), helpstring("method SetColor")] HRESULT SetColor([in] BSTR IdentLabel, [in] ULONG rgb, [in, defaultvalue(0)] BYTE Alpha);
[id(5), helpstring("method SetColor")] HRESULT SetColor([in] BSTR IdentLabel, [in] ULONG rgb, [in, defaultvalue(255)] BYTE Alpha);
[id(8), helpstring("method SetLabelFont")] HRESULT SetLabelFont([in] BSTR FontName, [in] DOUBLE FontHeight, [in, defaultvalue(0)] DOUBLE FontHeightSymbols);
[id(9), helpstring("method SetLabelPosition")] HRESULT SetLabelPosition([in, defaultvalue(1)] BYTE LabelPos);
[propget, id(10), helpstring("method ContoursXML")] HRESULT ContoursXML([out, retval] BSTR* pVal);
@@ -114,6 +114,7 @@ interface IAbout : IDispatch{
[propget, id(5), helpstring("property VersionMajor")] HRESULT VersionMajor([out, retval] LONG* pVal);
[propget, id(6), helpstring("property VersionMinor")] HRESULT VersionMinor([out, retval] LONG* pVal);
[propget, id(7), helpstring("property VersionString")] HRESULT VersionString([out, retval] BSTR* pVal);
[propget, id(8), helpstring("property usTimer")] HRESULT usTimer([out, retval] DOUBLE* pVal);
};
[
object,
@@ -222,7 +223,7 @@ interface IDWGPoint : IDispatch{
pointer_default(unique)
]
interface ISLNKContour : IDispatch{
[id(2), helpstring("method SetColor")] HRESULT SetColor([in] ULONG rgb, [in, defaultvalue(0)] BYTE Alpha);
[id(2), helpstring("method SetColor")] HRESULT SetColor([in] ULONG rgb, [in, defaultvalue(255)] BYTE Alpha);
[id(3), helpstring("method SetUrl")] HRESULT SetUrl([in] BSTR Url, [in] BSTR FriendlyName);
[propget, id(5), helpstring("property Area")] HRESULT Area([out, retval] DOUBLE* pVal);
[propget, id(6), helpstring("property Extents")] HRESULT Extents([out, retval] IBoundingBox ** pVal);
@@ -248,6 +249,7 @@ interface ISLNKSymbol : IDispatch{
[propget, id(3), helpstring("property Rotation")] HRESULT Rotation([out, retval] LONG* pVal);
[propput, id(3), helpstring("property Rotation")] HRESULT Rotation([in] LONG newVal);
[propget, id(4), helpstring("property Contour")] HRESULT Contour([out, retval] ISLNKContour** pVal);
[id(5), helpstring("method SetColor")] HRESULT SetColor([in] ULONG rgb, [in, defaultvalue(255)] BYTE Alpha);
};
[
object,

View File

@@ -1,6 +1,6 @@
// Zorg dat versies alfabetisch altijd op elkaar volgen!
#define SLNK_MAJOR_VERSION 2
#define SLNK_MINOR_VERSION 10
#define SLNK_MINOR_VERSION 11
#define SLNK_BUILD_VERSION 0
// Define resource strings

View File

@@ -74,3 +74,14 @@ STDMETHODIMP CSLNKSymbol::get_Contour(ISLNKContour** pVal)
return S_OK;
}
STDMETHODIMP CSLNKSymbol::SetColor(ULONG rgb, BYTE Alpha /*=255*/)
{
int b=rgb%256;
int g=(rgb>>8)%256;
int r=(rgb>>16)%256;
m_SLNKSymbol->m_Color.set(r, g, b, Alpha);
m_SLNKSymbol->m_ColorSet = true;
return S_OK;
}

View File

@@ -348,7 +348,7 @@ WT_Drawable *CSLNKSymbolDefinition::asBitmap(int pixeldx, int pixeldy, long pape
}
#endif
WT_Result CSLNKSymbolDefinition::serialize(WT_File & file)
WT_Result CSLNKSymbolDefinition::serialize(WT_File & file, WT_Color pColor, BOOL pColorSet)
{
if (m_AsBitmap)
{ // Wel even kopietje trekken omdat anders niet opnieuw getransformeerd wordt
@@ -369,6 +369,13 @@ WT_Result CSLNKSymbolDefinition::serialize(WT_File & file)
if (m_BuiltIn) // Die hebben alleen een bounding contour
return WT_Result::Success;
// Vertrouw de huidige rendition niet! Het eerste lijntje van een symbool kan default wit verwachten (CO206.DWF)
// Tijdens het serializen van het symbool hebben we niets met (desired)_rendition te maken
if (pColorSet)
pColor.serialize(file);
else
WT_Color(0,0,0).serialize(file); // Op de default zetten. TODO: Moet eigenlijk voor alle attributen
WT_Result result;
// Open onze symbool DWF
m_wtFile.set_file_mode(WT_File::File_Read);
@@ -425,6 +432,11 @@ WT_Result CSLNKSymbolDefinition::serialize(WT_File & file)
if (obj->object_id() == WT_Object::Color_ID)
{ // Misschien een zwart-wit toggle doorvoeren? Of zelfs highlight?
// m_iEPlotSection->get_PaperColor()
if (pColorSet) // Hoeven we niet steeds weer te zetten
{
break;
}
//else gewoon naar de default doorvallen
}
if (obj->object_id() == WT_Object::Viewport_ID)
{

View File

@@ -19,7 +19,7 @@ public:
WT_Logical_Point m_Center; // Wordt gezet bij berekenen boundingcontour
double m_dwgScale;
WT_Drawable *asBitmap(int pixeldx, int pixeldy, long paperColor);
WT_Result serialize(WT_File & file);
WT_Result serialize(WT_File & file, WT_Color pColor, BOOL pColorSet);
WT_Result calculateBoundary(WT_Polygon &m_BoundingContour, WT_Transform *tm=NULL);
private:

View File

@@ -8,6 +8,7 @@
CSLNKSymbolImpl::CSLNKSymbolImpl(void)
{
m_ColorSet = false;
}
CSLNKSymbolImpl::~CSLNKSymbolImpl(void)
@@ -21,6 +22,7 @@ CSLNKSymbolImpl::CSLNKSymbolImpl(double dwgX, double dwgY, CWhipFileState *State
m_symbolName = "";
m_Rotation = 0;
m_Scale = 1.0;
m_ColorSet = false;
m_SLNKContour.m_parentWhipFileState = State;
m_SLNKContour.m_fromSymbol=true;
}
@@ -80,9 +82,6 @@ WT_Result CSLNKSymbolImpl::serialize (WT_File & file, WT_Units & units,
file.desired_rendition().line_weight() = WT_Line_Weight(0);
}
#endif
// Vertrouw de huidige rendition niet! Het eerste lijntje van een symbool kan default wit verwachten (CO206.DWF)
// Tijdens het serializen van het symbool hebben we niets met (desired)_rendition te maken
WT_Color().serialize(file); // Op de default zetten. TODO: Moet eigenlijk voor alle attributen
double dx, dy;
@@ -133,7 +132,12 @@ WT_Result CSLNKSymbolImpl::serialize (WT_File & file, WT_Units & units,
else
#endif
{ //Gewone vector versie
symbdef->serialize(file);
if (m_ColorSet && m_Color.rgba().m_rgb.a==0)
{
// Skip want toch onzichtbaar
}
else
symbdef->serialize(file, m_Color, m_ColorSet);
}
#ifdef _DEBUG
@@ -156,6 +160,8 @@ WT_Result CSLNKSymbolImpl::serialize (WT_File & file, WT_Units & units,
// geroteerde symbolen overflow problemen)
//
#undef BOUNDINGBOX_HERBEREKENEN
#ifdef BOUNDINGBOX_HERBEREKENEN
WT_Polygon pl;
symbdef->calculateBoundary(pl, &SymbolTrans);
if (pl.count()>0)
@@ -163,6 +169,7 @@ WT_Result CSLNKSymbolImpl::serialize (WT_File & file, WT_Units & units,
m_SLNKContour.set(pl.count(), pl.points(), true);
}
else // Builtin of bitmap
#endif
{
m_SLNKContour.transform(SymbolTrans); // Pas op: de bounds zijn nu misschien nog verkeerd
}

View File

@@ -24,4 +24,6 @@ public:
int m_Rotation;
double m_Scale;
CSLNKContourImpl m_SLNKContour;
WT_Color m_Color;
BOOL m_ColorSet;
};

View File

@@ -600,7 +600,7 @@ bool CWhipFile::GenerateSymbols(myWT_File &my_file)
{
double scale = m_State.m_contunits.application_to_dwf_transform()(0,0);
// TODO: Echt uniek layernum (en URL num) bepalen
my_file.desired_rendition().layer() = WT_Layer(my_file, 1000, "SLNK Symbols");
my_file.desired_rendition().layer() = WT_Layer(my_file, 100000, "SLNK Symbols");
for (size_t i=0; i<m_State.m_SLNKSymbols.GetCount(); i++)
{
@@ -639,7 +639,7 @@ bool CWhipFile::GenerateSymbolLabels(myWT_File &my_file)
clr.serialize(my_file); // Vertrouw niets. Expliciete serialize. Zie @@@
// TODO: Echt uniek layernum (en URL num) bepalen
my_file.desired_rendition().layer() = WT_Layer(my_file, 1001, "SLNK Symbol Labels");
my_file.desired_rendition().layer() = WT_Layer(my_file, 100001, "SLNK Symbol Labels");
for (size_t i=0; i<m_State.m_SLNKSymbols.GetCount(); i++)
{
CSLNKSymbolImpl *symbol= m_State.m_SLNKSymbols[i];
@@ -652,7 +652,7 @@ bool CWhipFile::GenerateSymbolLabels(myWT_File &my_file)
WT_Transform wasTransform = my_file.heuristics().transform();
WT_Boolean wasApplyTransform = my_file.heuristics().apply_transform();
my_file.heuristics().set_apply_transform(WD_False); // Hebben we al rechtstreeks op de contour gedaan
symbol->m_SLNKContour.SerializeLabel(my_file, CSLNKContourImpl::LABEL_OUTSIDEBOTTOM, fontheight, myDC);
symbol->m_SLNKContour.SerializeLabel(my_file, CSLNKContourImpl::LABEL_OUTSIDEBOTTOM, fontheight, scale, myDC);
// En transform weer terug
my_file.heuristics().set_transform(wasTransform);
my_file.heuristics().set_apply_transform(wasApplyTransform);
@@ -680,7 +680,7 @@ bool CWhipFile::GenerateContouren(WT_File &my_planfile, myWT_File &my_file,
WT_Object_Node current_node = my_file.desired_rendition().object_node();
// TODO: Echt uniek layernum (en URL num) bepalen
my_file.desired_rendition().layer() = WT_Layer(my_file, 1002, "SLNK Contours");
my_file.desired_rendition().layer() = WT_Layer(my_file, 100002, "SLNK Contours");
for (size_t i=0; i<m_State.m_SLNKContouren.GetCount(); i++)
{
@@ -708,7 +708,7 @@ bool CWhipFile::GenerateLabels(WT_File &my_planfile, myWT_File &my_file, double
WT_Color keepColor = my_planfile.rendition().color();
// TODO: Echt uniek layernum (en URL num) bepalen
my_file.desired_rendition().layer() = WT_Layer(my_file, 1003, "SLNK Labels");
my_file.desired_rendition().layer() = WT_Layer(my_file, 100003, "SLNK Labels");
// Zet een DC op om bij 'Center' de afmetingen van de tekst te kunnen bepalen
int fontheight= myRound(m_FontHeight * scale);
@@ -729,7 +729,7 @@ bool CWhipFile::GenerateLabels(WT_File &my_planfile, myWT_File &my_file, double
if (contour->m_contLabel.length()!=0 && contour->m_ExtraLabel != "")
{ // We have got a proper label/contour
// Alle teksten tekenen
contour->SerializeLabel(my_file, m_LabelPos, fontheight, myDC);
contour->SerializeLabel(my_file, m_LabelPos, fontheight, scale, myDC);
}
}
@@ -865,7 +865,7 @@ STDMETHODIMP CWhipFile::SetLabel(BSTR IdentLabel, BSTR ExtraLabel)
// mei 2007: DEPRECATED
// Lege Identlabel zet alle ruimtes op dezelfde kleur
STDMETHODIMP CWhipFile::SetColor(BSTR IdentLabel, ULONG rgb, BYTE Alpha /*=0*/)
STDMETHODIMP CWhipFile::SetColor(BSTR IdentLabel, ULONG rgb, BYTE Alpha /*=255*/)
{
try {
for (size_t i=0; i<m_State.m_SLNKContouren.GetCount(); i++)

View File

@@ -64,6 +64,7 @@ private:
public:
STDMETHOD(SetColor)(ULONG rgb, BYTE Alpha);
STDMETHOD(get_Scale)(DOUBLE* pVal);
STDMETHOD(put_Scale)(DOUBLE newVal);
STDMETHOD(get_Rotation)(LONG* pVal);

View File

@@ -87,39 +87,39 @@ Subject 1.02: How do I find the distance from a point to a line?
Let the point be C (Cx,Cy) and the line be AB (Ax,Ay) to (Bx,By).
Let P be the point of perpendicular projection of C on AB. The parameter
r, which indicates P's position along AB, is computed by the dot product
r, which indicates P's position along AB, is computed by the dot product
of AC and AB divided by the square of the length of AB:
(1) AC dot AB
r = ---------
r = ---------
||AB||^2
r has the following meaning:
r=0 P = A
r=1 P = B
r<0 P is on the backward extension of AB
r>1 P is on the forward extension of AB
0<r<1 P is interior to AB
The length of a line segment in d dimensions, AB is computed by:
L = sqrt( (Bx-Ax)^2 + (By-Ay)^2 + ... + (Bd-Ad)^2)
so in 2D:
so in 2D:
L = sqrt( (Bx-Ax)^2 + (By-Ay)^2 )
and the dot product of two vectors in d dimensions, U dot V is computed:
D = (Ux * Vx) + (Uy * Vy) + ... + (Ud * Vd)
so in 2D:
D = (Ux * Vx) + (Uy * Vy)
so in 2D:
D = (Ux * Vx) + (Uy * Vy)
So (1) expands to:
(Cx-Ax)(Bx-Ax) + (Cy-Ay)(By-Ay)
r = -------------------------------
L^2
@@ -131,7 +131,7 @@ Subject 1.02: How do I find the distance from a point to a line?
And the distance from A to P = r*L.
Use another parameter s to indicate the location along PC, with the
Use another parameter s to indicate the location along PC, with the
following meaning:
s<0 C is left of AB
s>0 C is right of AB
@@ -155,7 +155,7 @@ Subject 1.02: How do I find the distance from a point to a line?
//
double px = ax + r*(bx-ax);
double py = ay + r*(by-ay);
//
//
double s = ((ay-cy)*(bx-ax)-(ax-cx)*(by-ay) ) / r_denomenator;
distanceLine = fabs(s)*sqrt(r_denomenator);
@@ -196,10 +196,10 @@ Subject 1.02: How do I find the distance from a point to a line?
// Vind de hoek van de edge van ps die het dichts bij pt ligt
// (het maakt ons niet uit of pt er binnen of buiten ligt)
// A = P2Y - P1Y
// B = P1X - P2X
// C = P2X * P1Y - P2Y * P1X
// DistToLine = Abs((A * PX + B * PY + C) / Sqr(A * A + B * B))
// A = P2Y - P1Y
// B = P1X - P2X
// C = P2X * P1Y - P2Y * P1X
// DistToLine = Abs((A * PX + B * PY + C) / Sqr(A * A + B * B))
/*static*/ void CSLNKContourImpl::EdgeAngle(const WT_Logical_Point pt, const WT_Point_Set &ps, double &EdgeAngle, double &EdgeDistance)
{
double ptx = pt.m_x;
@@ -217,11 +217,11 @@ Subject 1.02: How do I find the distance from a point to a line?
pt1.m_x, pt1.m_y,
pt2.m_x, pt2.m_y,
DistSeg, DistLine);
// Bij een 'ingedeukte' ruimte kan DistSeg == minDistSeg zijn. Dan wil
// je juist een zo'n groot mogelijke afstand tot de virtuele projectie
if (DistSeg < minDistSeg || (DistSeg == minDistSeg && DistLine > minDistLine))
{
{
long dy = pt2.m_y - pt1.m_y;
long dx = pt2.m_x - pt1.m_x;
@@ -243,7 +243,7 @@ Subject 1.02: How do I find the distance from a point to a line?
EdgeDistance = minDistLine; //We rekenen met Seg maar projecteren uiteindelijk op Line
}
// Signed Area needed for centroid!
// Signed Area needed for centroid!
// Negative is clockwise, Positve counterclockwise
/*static*/double CSLNKContourImpl::DWFArea(const WT_Point_Set &pg)
{
@@ -322,7 +322,9 @@ WT_Logical_Point CSLNKContourImpl::LabelPosition(LABELPOS pos /*= LABEL_DEFAULT*
return WT_Logical_Point((WT_Integer32)(ptx / dDWFArea6), (WT_Integer32)(pty / dDWFArea6));
}
void CSLNKContourImpl::SerializeLabel(WT_File &my_file, LABELPOS pos, int fontheight, HDC myDC)
void CSLNKContourImpl::SerializeLabel(WT_File &my_file, LABELPOS pos,
int fontheight, double scale,
HDC myDC)
{
if (m_Color.rgba().m_rgb.a==255)
{ // Volle achtergrond kleur
@@ -345,7 +347,7 @@ void CSLNKContourImpl::SerializeLabel(WT_File &my_file, LABELPOS pos, int fonthe
tok.Replace("[BR]", "\n"); // We ondersteunen ook [BR] als newline
WT_Logical_Point ptTxt = LabelPosition(pos);
// De wiskundige label-positie is bepaald. Nu iets corrigeren om
// De wiskundige label-positie is bepaald. Nu iets corrigeren om
// (afhankelijk van het font) mooier te zijn
// Ook eventueel hori/vert centreren
int width = -1; // Voor UBB code [c] van centreren
@@ -361,7 +363,7 @@ void CSLNKContourImpl::SerializeLabel(WT_File &my_file, LABELPOS pos, int fonthe
{
// Eerst een keer simuleren om grootte te bepalen
ATLASSERT(myDC!=NULL);
WT_Logical_Point ptBR = DrawOneLabel(my_file, pos, ptTxt, tok, fontheight, myDC);
WT_Logical_Point ptBR = DrawOneLabel(my_file, ptTxt, tok, fontheight, scale, myDC);
width = (ptBR.m_x - ptTxt.m_x);
ptTxt.m_y -= (ptBR.m_y - ptTxt.m_y)/2 + fontheight*9/10;
ptTxt.m_x += fontheight/4;
@@ -371,7 +373,7 @@ void CSLNKContourImpl::SerializeLabel(WT_File &my_file, LABELPOS pos, int fonthe
{
// Eerst een keer simuleren om grootte te bepalen
ATLASSERT(myDC!=NULL);
WT_Logical_Point ptBR = DrawOneLabel(my_file, pos, ptTxt, tok, fontheight, myDC);
WT_Logical_Point ptBR = DrawOneLabel(my_file, ptTxt, tok, fontheight, scale, myDC);
width = (ptBR.m_x - ptTxt.m_x);
ptTxt.m_y -= fontheight;
ptTxt.m_x -= (ptBR.m_x - ptTxt.m_x)/2;
@@ -383,7 +385,7 @@ void CSLNKContourImpl::SerializeLabel(WT_File &my_file, LABELPOS pos, int fonthe
if (!CSLNKContourImpl::PointInPolygon(ptTxt, *this))
ptTxt = LabelPosition(CSLNKContourImpl::LABEL_DEFAULT);
// Eerst een keer simuleren om grootte te bepalen
WT_Logical_Point ptBR = DrawOneLabel(my_file, pos, ptTxt, tok, fontheight, myDC);
WT_Logical_Point ptBR = DrawOneLabel(my_file, ptTxt, tok, fontheight, scale, myDC);
width = (ptBR.m_x - ptTxt.m_x);
ptTxt.m_x -= (ptBR.m_x - ptTxt.m_x)/2;
ptTxt.m_y -= (ptBR.m_y - ptTxt.m_y)/2 + fontheight*9/10;
@@ -400,7 +402,7 @@ pm.serialize(my_file);
}
// Nu echt tekenen met width<>-2
DrawOneLabel(my_file, pos, ptTxt, tok, fontheight, myDC, width);
DrawOneLabel(my_file, ptTxt, tok, fontheight, scale, myDC, width);
}
// Draw one (possibly multline) label
@@ -409,15 +411,15 @@ pm.serialize(my_file);
// Als width==-1 is centreren niet mogelijk/nodig
// Als width>0 is centreren mogelijk via [c]
WT_Logical_Point CSLNKContourImpl::DrawOneLabel(WT_File &my_file,
LABELPOS pos,
WT_Logical_Point ptTxt,
CString tok,
int fontheight,
int fontheight,
double scale,
HDC myDC,
int width/*=-2*/)// Voor centreren. Moet aanroeper al een keer bepaald hebben
{
long max_width=0; // Bepaal hiermee 'rechtsonder' van de tekst als myDC
//TODO: UBB sluitcodes ondersteunen
int curpos = 0;
CString token = tok.Tokenize("\n", curpos);
@@ -425,9 +427,12 @@ WT_Logical_Point CSLNKContourImpl::DrawOneLabel(WT_File &my_file,
bool centering=false;
while( token != "" )
{
// invariant (ook bij binnenkomst): ptTxt.m_y bevat het linksonderpunt van de huidige regel
// uitgaande van fontheight. Bij [s] gebruik moeten we dus corrigeren
//CString f(token);
int skipextra = 0; // Extra skip bij underline
long size=100;
int thisLineHeight=fontheight; // mooie default
// Supported UBB-like codes:
// [[This is literal text in square brackets]
@@ -435,9 +440,10 @@ WT_Logical_Point CSLNKContourImpl::DrawOneLabel(WT_File &my_file,
// [b]This text is bold
// [u]This text is underline
// [cFF00FF]This text is colored
// [s50]This text is 50% sized
// [s50]This text is 50% sized van standaard labelfont
// [S800]This text is 800 height sized
// Bovenstaand alleen voor de huidige regel
// [c] Centreer alle regels binnen bounding box (anders links gealigned)
// [c] Centreer alle(!) volgende regels binnen bounding box (anders links gealigned)
while (token[0] == '[')
{
token.Delete(0);
@@ -467,7 +473,7 @@ WT_Logical_Point CSLNKContourImpl::DrawOneLabel(WT_File &my_file,
if (end==1)
{
token.Delete(0);
if (width>0) centering = true;
centering = true;
break;
}
if (end >= 0)
@@ -485,15 +491,21 @@ WT_Logical_Point CSLNKContourImpl::DrawOneLabel(WT_File &my_file,
}
case 's': // Size
{
BOOL bigS = (token[0]=='S');
int end = token.Find(']');
if (end >= 0)
{
if (sscanf(token, "s%d]", &size))
token.Delete(0);
if (sscanf(token, "%d]", &size))
{
int fh = myRound(double(size)*fontheight/100);
ptTxt.m_y += (fontheight - fh);
if (bigS)
thisLineHeight = myRound(size * scale);
else
thisLineHeight = myRound(double(size)*fontheight/100);
ptTxt.m_y -= (thisLineHeight - fontheight); // Correctie op de invariant voor huidige regel
if (width != -2)
my_file.desired_rendition().font().height() = fh;
my_file.desired_rendition().font().height() = thisLineHeight;
}
token.Delete(0, end);
}
@@ -511,7 +523,7 @@ WT_Logical_Point CSLNKContourImpl::DrawOneLabel(WT_File &my_file,
RECT rc = { 0, 0, 0, 0};
DrawText(myDC, token, token.GetLength(), &rc, DT_CALCRECT); // Grootte bepalen
// Tekst horizontaal centreren
horoffset = width/2 - MulDiv(rc.right*size/100,fontheight,FONT_SIZER)/2;
horoffset = width/2 - MulDiv(rc.right,thisLineHeight,FONT_SIZER)/2;
}
WT_String txt;
if (WT_String::is_ascii(token.GetLength(), token))
@@ -543,7 +555,7 @@ WT_Logical_Point CSLNKContourImpl::DrawOneLabel(WT_File &my_file,
// Tekst horizontaal en verticaal centreren
// ptRes.m_y += rc.bottom; halen we wel uit ptY
max_width = max(max_width, MulDiv(rc.right,size,100));
max_width = max(max_width, MulDiv(rc.right,thisLineHeight,fontheight));
}
line ++;
@@ -568,7 +580,7 @@ WT_Logical_Point CSLNKContourImpl::DrawOneLabel(WT_File &my_file,
- (m_fromSymbol) Symbool (al dan niet met m_Key gedefinieerd)
- Ingebouwd (star)
- Gedefinieerd (bounding octagon)
Als solidOnly dan alleen als alpha==255 en een label (wel herkend)
****************************************************************************/
WT_Result CSLNKContourImpl::serialize(WT_File & file, BOOL solidOnly)
@@ -588,7 +600,7 @@ WT_Result CSLNKContourImpl::serialize(WT_File & file, BOOL solidOnly)
{ // We have got a proper label/contour
if (m_fromSymbol ||
(m_Color.rgba().m_rgb.a==255 && solidOnly) ||
(m_Color.rgba().m_rgb.a<255 && !solidOnly))
(m_Color.rgba().m_rgb.a<255 && !solidOnly))
{
// Start a node for 'everything'. Dit is wat we concreet teruggeven bij klikken in de tekening
WT_Object_Node my_node(file,m_next_node_num++,m_Key);
@@ -617,11 +629,11 @@ WT_Result CSLNKContourImpl::serialize(WT_File & file, BOOL solidOnly)
WT_RGBA32 rgba[3];
WT_RGBA32 clr(this.m_Color.rgba());
rgba[0] = clr;
rgba[1] = WT_RGBA32 (clr.m_rgb.r+64>255?255:clr.m_rgb.r+64,
clr.m_rgb.g+64>255?255:clr.m_rgb.g+64,
rgba[1] = WT_RGBA32 (clr.m_rgb.r+64>255?255:clr.m_rgb.r+64,
clr.m_rgb.g+64>255?255:clr.m_rgb.g+64,
clr.m_rgb.b+64>255?255:clr.m_rgb.b+64, clr.m_rgb.a);
rgba[1] = WT_RGBA32 (clr.m_rgb.r-64<0?0:clr.m_rgb.r-64,
clr.m_rgb.g-64<0?0:clr.m_rgb.g-64,
rgba[1] = WT_RGBA32 (clr.m_rgb.r-64<0?0:clr.m_rgb.r-64,
clr.m_rgb.g-64<0?0:clr.m_rgb.g-64,
clr.m_rgb.b-64<0?0:clr.m_rgb.b-64, clr.m_rgb.a);
rgba[2] = rgba[1];

View File

@@ -54,12 +54,13 @@ public:
WT_Logical_Point LabelPosition(LABELPOS pos = LABEL_DEFAULT);
void SerializeLabel(WT_File &my_file, LABELPOS pos,
int fontheight,
double scale,
HDC myDC);
WT_Logical_Point DrawOneLabel(WT_File &my_file,
LABELPOS pos,
WT_Logical_Point ptTxt,
CString tok,
int fontheight,
double scale,
HDC myDC, int width=-2);
static WT_Integer32 m_next_node_num;

View File

@@ -62,21 +62,22 @@ STDMETHODIMP CWhip2DCImpl::Load(HDC hDC, CEPlotSectionImpl *EPlotStream,
m_State.m_mul=0;
my_input_file.set_file_mode(WT_File::File_Read);
if (0) { // altijd 'gewoon' recht rekenen
if (m_State.m_lRotation != 0)
{
WT_Logical_Point lCenter(0,0);
WT_Transform trans(lCenter, 1.0, 1.0, m_State.m_lRotation);
my_input_file.heuristics().set_transform(trans);
m_State.m_Trans = WT_Transform(lCenter, 1.0, 1.0, m_State.m_lRotation);
my_input_file.heuristics().set_transform(m_State.m_Trans);
my_input_file.heuristics().set_apply_transform(true);
my_input_file.rendition().font().rotation() = MulDiv(m_State.m_lRotation,16384,90);
}
}
WT_Result result;
if (my_input_file.open() != WT_Result::Success)
throw myCString("\nCWhip2DCImpl::Load: unable to open file '%s'", m_WhipPath.ascii());
BOOL ViewportDone = FALSE;
double dScale = 0.0;
double dScale = 1.0;
// Doorloop de DWF totdat alles gelezen is
// Stop als we een view/viewport hebben (dan wordt m_mul gezet) tenzij maximize, dan lezen we alles
while ((result = my_input_file.process_next_object()) == WT_Result::Success
@@ -92,6 +93,21 @@ STDMETHODIMP CWhip2DCImpl::Load(HDC hDC, CEPlotSectionImpl *EPlotStream,
WT_View *view = (WT_View *)my_input_file.current_object();
if (!maximize)
m_State.SetExtents(view->view()); // m_mul wordt gezet en de loop eindigt
else
{
// 'Move' alles naar het midden van het eerste kwadrant
// Anders kunnen we later bij bounds bepaling overflow krijgen
// Waar roteren we eigenlijk omheen?
WT_Logical_Point lCenter;
if (m_State.m_lRotation==0||m_State.m_lRotation==90||m_State.m_lRotation==180||m_State.m_lRotation==270)
lCenter = WT_Logical_Point(INT_MAX/2,INT_MAX/2);
else
lCenter = WT_Logical_Point(0, 0);
m_State.m_Trans = WT_Transform (lCenter, 1.0, 1.0, m_State.m_lRotation);
my_input_file.heuristics().set_transform(m_State.m_Trans);
}
break;
}
if (obj->object_id() == WT_Object::Viewport_ID)
@@ -140,6 +156,7 @@ STDMETHODIMP CWhip2DCImpl::Load(HDC hDC, CEPlotSectionImpl *EPlotStream,
}
}
result = my_input_file.close(); // closing Input file.
if (m_State.m_mul==0 && result == WT_Result::Success)
{ // Blijkbaar geen view en/of viewport gevonden
m_State.SetExtents(m_State.m_MinMax); // Die hebben we dan in de vorige slag wel bepaald
@@ -223,9 +240,7 @@ STDMETHODIMP CWhip2DCImpl::Paint(VARIANT_BOOL forceBW)
if (m_State.m_lRotation != 0) // Tijdens het laden roteren
{
WT_Logical_Point lCenter(0,0);
WT_Transform trans(lCenter, 1.0, 1.0, m_State.m_lRotation);
my_input_file.heuristics().set_transform(trans);
my_input_file.heuristics().set_transform(m_State.m_Trans);
my_input_file.heuristics().set_apply_transform(true);
}

View File

@@ -67,6 +67,7 @@ public:
BOOL m_Maximize;
BOOL m_centerImage;
long m_lRotation;
WT_Transform m_Trans; // Voor tijdens rotatie
double m_mul; // schaal onze DWF-coordinaten naar bitmap coordinaten
CSize m_Size;

View File

720
Whiptk702/ellipse.cpp Normal file
View File

@@ -0,0 +1,720 @@
// 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;
}

1065
Whiptk702/font_options.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,99 @@
// 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/logical_point.cpp 1 9/12/04 8:54p Evansg $
#include "whiptk/pch.h"
///////////////////////////////////////////////////////////////////////////
WT_Boolean WT_Logical_Point::operator== (WT_Logical_Point_16 const & lp) const
{
if (m_x == (WT_Integer32)lp.m_x &&
m_y == (WT_Integer32)lp.m_y)
return WD_True;
else
return WD_False;
}
///////////////////////////////////////////////////////////////////////////
WT_Logical_Point const & WT_Logical_Point::operator= (WT_Logical_Point_16 const & in)
{
m_x = (WT_Integer32) in.m_x;
m_y = (WT_Integer32) in.m_y;
return *this;
}
///////////////////////////////////////////////////////////////////////////
const double myPI = 3.14159265358979323846;
/////////////////////////
WT_Logical_Point const WT_Logical_Point::operator* (WT_Transform const & trans) const
{
WT_Logical_Point new_point;
// new_point.m_x = (WT_Integer32) ( ((double)m_x + trans.m_translate.m_x) * trans.m_x_scale );
// new_point.m_y = (WT_Integer32) ( ((double)m_y + trans.m_translate.m_y) * trans.m_y_scale );
switch (trans.rotation())
{
case 0:
new_point.m_x = (WT_Integer32) (((double)m_x * trans.m_x_scale) + trans.m_translate.m_x);
new_point.m_y = (WT_Integer32) (((double)m_y * trans.m_y_scale) + trans.m_translate.m_y);
break;
case 90:
new_point.m_x = 0x7FFFFFFF - ((WT_Integer32) (((double)m_y * trans.m_y_scale) + trans.m_translate.m_y));
new_point.m_y = (WT_Integer32) (((double)m_x * trans.m_x_scale) + trans.m_translate.m_x);
break;
case 180:
new_point.m_x = 0x7FFFFFFF - ((WT_Integer32) (((double)m_x * trans.m_x_scale) + trans.m_translate.m_x));
new_point.m_y = 0x7FFFFFFF - ((WT_Integer32) (((double)m_y * trans.m_y_scale) + trans.m_translate.m_y));
break;
case 270:
new_point.m_x = (WT_Integer32) (((double)m_y * trans.m_y_scale) + trans.m_translate.m_y);
new_point.m_y = 0x7FFFFFFF - ((WT_Integer32) (((double)m_x * trans.m_x_scale) + trans.m_translate.m_x));
break;
default:
{
// Merk op: de code hierboven roteert om (INT_MAX/2, INT_MAX/2)
// Bij 90 graden rotaties heb je dan geen kans op overflow.
// Bij andere hoeken kan het wel mis gaan. Wij roteren hieronder
// daarom om 0,0. Dat blijkt in de praktijk goed te gaan?
double sinAngle = sin((double)trans.rotation() / 180.0 * myPI);
double cosAngle = cos((double)trans.rotation() / 180.0 * myPI);
double transx = (double)m_x * trans.m_x_scale + trans.m_translate.m_x;
double transy = (double)m_y * trans.m_y_scale + trans.m_translate.m_y;
double newx = transx * cosAngle - transy * sinAngle;
double newy = transy * cosAngle + transx * sinAngle;
// if (newx>INT_MAX || newy>INT_MAX || newx<INT_MIN || newy<INT_MIN)
// DebugBreak();
new_point.m_x = (WT_Integer32)newx;
new_point.m_y = (WT_Integer32)newy;
//throw WT_Result::Internal_Error;
}
}
return new_point;
}
///////////////////////////////////////////////////////////////////////////
WT_Logical_Point const WT_Logical_Point::operator*= (WT_Transform const & trans)
{
// Need a temp copy since with some rotations will be mucking with intermediate terms
WT_Logical_Point orig_point(m_x, m_y);
*this = orig_point * trans;
return *this;
}

855
Whiptk702/text.cpp Normal file
View File

@@ -0,0 +1,855 @@
// 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: /Components/Internal/DWF Toolkit/v7.0.1/develop/global/src/dwf/whiptk/text.cpp 5 5/09/05 12:39a Evansg $
#include "whiptk/pch.h"
#include <stddef.h>
#include <assert.h>
///////////////////////////////////////////////////////////////////////////
WT_Text::WT_Text (WT_Text const &in)
: WT_Drawable()
, m_position(in.m_position)
, m_string(in.m_string)
, m_option_bounds(in.m_option_bounds)
, m_option_overscore(in.m_option_overscore)
, m_option_underscore(in.m_option_underscore)
, m_option_reserved(in.m_option_reserved)
, m_stage(in.m_stage)
, m_transformed(in.m_transformed)
, m_relativized(in.m_relativized)
, m_optioncode(in.m_optioncode)
, m_obsolete_font_holder(in.m_obsolete_font_holder)
, m_obsolete_length_holder(in.m_obsolete_length_holder)
, m_obsolete_msg_holder(in.m_obsolete_msg_holder)
{
}
///////////////////////////////////////////////////////////////////////////
WT_Text & WT_Text::operator= (WT_Text const & in)
{
m_position = in.m_position;
m_string = in.m_string;
m_option_bounds = in.m_option_bounds;
m_option_overscore = in.m_option_overscore;
m_option_underscore = in.m_option_underscore;
m_option_reserved = in.m_option_reserved;
m_stage = in.m_stage;
m_transformed = in.m_transformed;
m_relativized = in.m_relativized;
m_optioncode = in.m_optioncode;
m_obsolete_font_holder = in.m_obsolete_font_holder;
m_obsolete_length_holder = in.m_obsolete_length_holder;
m_obsolete_msg_holder = in.m_obsolete_msg_holder;
return *this;
}
///////////////////////////////////////////////////////////////////////////
WT_Text::WT_Text ()
: m_position (WT_Logical_Point (0,0))
, m_stage (Getting_Started)
, m_transformed (WD_False)
, m_relativized (WD_False)
, m_obsolete_font_holder (WD_Null)
{ }
///////////////////////////////////////////////////////////////////////////
WT_Text::~WT_Text()
{
if (m_obsolete_font_holder)
delete m_obsolete_font_holder;
}
///////////////////////////////////////////////////////////////////////////
WT_Text::WT_Text (WT_Logical_Point const & position,
WT_String const & string,
WT_Logical_Point const * bounds,
WT_Unsigned_Integer16 overscore_count,
WT_Unsigned_Integer16 const * overscore_pos,
WT_Unsigned_Integer16 underscore_count,
WT_Unsigned_Integer16 const * underscore_pos)
: m_position (position)
, m_string(string)
, m_stage (Getting_Started)
, m_transformed (WD_False)
, m_relativized (WD_False)
, m_obsolete_font_holder (WD_Null)
{
m_option_bounds.set(bounds);
if (overscore_count)
m_option_overscore.set(overscore_count, overscore_pos);
if (underscore_count)
m_option_underscore.set(underscore_count, underscore_pos);
}
///////////////////////////////////////////////////////////////////////////
WT_Text::WT_Text (WT_Logical_Point const & position,
WT_String const & string)
: m_position (position)
, m_string(string)
, m_stage (Getting_Started)
, m_transformed (WD_False)
, m_relativized (WD_False)
, m_obsolete_font_holder (WD_Null)
{
}
///////////////////////////////////////////////////////////////////////////
WT_Object::WT_ID WT_Text::object_id() const
{
return Text_ID;
}
///////////////////////////////////////////////////////////////////////////
#if DESIRED_CODE(WHIP_OUTPUT)
WT_Result WT_Text::serialize(WT_File & file) const
{
WD_CHECK (file.dump_delayed_drawable());
// BPM: This is a hack, but is the best I can do for now.
// Here's the issue: if Tahoe has set the heuristic to flip landscape into portrait,
// then we actually need the Font attribute to have a different rotation.
// The rotation code will do the adjustment, but we need to make sure that
// the rendition sync code "thinks" the font attribute might need updating.
file.desired_rendition().font().rotation() = file.desired_rendition().font().rotation();
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::Line_Weight_Bit |
WT_Rendition::Pen_Pattern_Bit |
// WT_Rendition::Line_Pattern_Bit |
// WT_Rendition::Line_Caps_Bit |
// WT_Rendition::Line_Join_Bit |
// WT_Rendition::Marker_Size_Bit |
// WT_Rendition::Marker_Symbol_Bit |
WT_Rendition::URL_Bit |
WT_Rendition::Layer_Bit |
WT_Rendition::Viewport_Bit |
WT_Rendition::Font_Extension_Bit |
WT_Rendition::Font_Bit |
WT_Rendition::Object_Node_Bit;
WD_CHECK (file.desired_rendition().sync(file, parts_to_sync));
if (file.heuristics().apply_transform())
((WT_Text *)this)->transform (file.heuristics().transform());
if (file.heuristics().allow_binary_data())
{
((WT_Text *)this)->relativize(file);
if (m_option_bounds.bounds() ||
m_option_overscore.count() ||
m_option_underscore.count())
{
// Advanced binary text
WD_CHECK (file.write((WT_Byte) 0x18)); // CTRL-X
WD_CHECK (file.write(1, &m_position));
WD_CHECK (m_string.serialize(file, WD_True));
WD_CHECK (m_option_overscore.serialize(*this, file));
WD_CHECK (m_option_underscore.serialize(*this, file));
WD_CHECK (m_option_bounds.serialize(*this, file));
if (file.heuristics().target_version() >= REVISION_WHEN_PACKAGE_FORMAT_BEGINS)
WD_CHECK (m_option_reserved.serialize(*this, file));
}
else
{
// Basic binary text
WD_CHECK (file.write((WT_Byte) 'x'));
WD_CHECK (file.write(1, &m_position));
WD_CHECK (m_string.serialize(file, WD_True));
}
} // if (allow binary data)
else
{
// Extended ASCII
// Don't relativize ASCII objects
WD_CHECK (file.write_geom_tab_level());
WD_CHECK (file.write("(Text "));
WD_CHECK (file.write_ascii(m_position));
WD_CHECK (file.write((WT_Byte) ' '));
WD_CHECK (m_string.serialize(file));
WD_CHECK (m_option_overscore.serialize(*this, file));
WD_CHECK (m_option_underscore.serialize(*this, file));
WD_CHECK (m_option_bounds.serialize(*this, file));
if (file.heuristics().target_version() >= REVISION_WHEN_PACKAGE_FORMAT_BEGINS)
WD_CHECK (m_option_reserved.serialize(*this, file));
WD_CHECK (file.write((WT_Byte) ')'));
} // else (extended ASCII output)
return WT_Result::Success;
}
#else
WT_Result WT_Text::serialize(WT_File &) const
{
return WT_Result::Success;
}
#endif // DESIRED_CODE()
///////////////////////////////////////////////////////////////////////////
WT_Result WT_Text::materialize(WT_Opcode const & opcode, WT_File & file)
{
switch (opcode.type())
{
case WT_Opcode::Single_Byte:
{
if (file.rendition().drawing_info().decimal_revision() < REVISION_WHEN_DRAW_TEXT_ATTRIBUTES_REMOVED)
return materialize_obsolete_form(opcode, file); // Old obsolete version of DrawText opcode
else
{
// Current version of DrawText opcode
switch (opcode.token()[0])
{
case 0x18: // Ctrl-X
{
switch (m_stage)
{
case Getting_Started:
m_stage = Getting_Position;
// No break;
case Getting_Position:
WD_CHECK (file.read(1, &m_position));
m_stage = Getting_String;
// No break
case Getting_String:
WD_CHECK (m_string.materialize(file));
m_stage = Getting_Overscore;
// No break
case Getting_Overscore:
WD_CHECK (m_option_overscore.materialize(*this, m_optioncode, file));
m_stage = Getting_Underscore;
// No break
case Getting_Underscore:
WD_CHECK (m_option_underscore.materialize(*this, m_optioncode, file));
m_stage = Getting_Bounds;
// No break
case Getting_Bounds:
WD_CHECK (m_option_bounds.materialize(*this, m_optioncode, file));
m_stage = Getting_Reserved;
// No break
case Getting_Reserved:
if (file.rendition().drawing_info().decimal_revision() >= REVISION_WHEN_PACKAGE_FORMAT_BEGINS)
WD_CHECK (m_option_reserved.materialize(*this, m_optioncode, file));
m_stage = Completed;
break;
default:
return WT_Result::Internal_Error;
}
} // case Ctrl-X
break;
case 'x':
{
switch (m_stage)
{
case Getting_Started:
m_stage = Getting_Position;
// No break
case Getting_Position:
WD_CHECK (file.read(1, &m_position));
m_stage = Getting_String;
// No break
case Getting_String:
WD_CHECK (m_string.materialize(file));
m_stage = Completed;
break;
default:
return WT_Result::Internal_Error;
} // switch (m_stage)
} break; // case 'x'
default:
return WT_Result::Opcode_Not_Valid_For_This_Object; // Illegal opcode token
} // switch (opcode token)
} // else (current version of DrawText)
m_relativized = WD_True;
de_relativize(file);
} break;
case WT_Opcode::Extended_ASCII:
{
switch (m_stage)
{
case Getting_Started:
m_stage = Getting_Position;
// No break
case Getting_Position:
WD_CHECK (file.read_ascii(m_position));
m_stage = Getting_String;
// No break
case Getting_String:
WD_CHECK (m_string.materialize(file));
m_stage = Getting_Next_Optioncode;
// No break
Getting_Next_Optioncode_Hop:
case Getting_Next_Optioncode:
WD_CHECK(m_optioncode.get_optioncode(file));
if (m_optioncode.type() == WT_Opcode::Null_Optioncode)
{
m_stage = Skipping_Last_Paren;
goto Skipping_Last_Paren_Hop;
}
m_stage = Materializing_Option;
// No Break;
case Materializing_Option:
switch (m_optioncode.option_id())
{
case WT_Text_Optioncode::Overscore_Option:
WD_CHECK(m_option_overscore.materialize(*this, m_optioncode, file));
break;
case WT_Text_Optioncode::Underscore_Option:
WD_CHECK(m_option_underscore.materialize(*this, m_optioncode, file));
break;
case WT_Text_Optioncode::Bounds_Option:
WD_CHECK(m_option_bounds.materialize(*this, m_optioncode, file));
break;
case WT_Text_Optioncode::Reserved_Option:
WD_CHECK(m_option_reserved.materialize(*this, m_optioncode, file));
break;
case WT_Text_Optioncode::Unknown_Option:
WD_CHECK(m_optioncode.skip_past_matching_paren(file));
break;
default:
return WT_Result::Internal_Error;
} // switch (m_sub_option.option_id())
m_stage = Getting_Next_Optioncode;
goto Getting_Next_Optioncode_Hop;
Skipping_Last_Paren_Hop:
case Skipping_Last_Paren:
WD_CHECK (opcode.skip_past_matching_paren(file));
m_stage = Completed;
break;
default:
return WT_Result::Internal_Error;
} // switch (m_stage)
} break; // ASCII
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;
return WT_Result::Success;
}
///////////////////////////////////////////////////////////////////////////
WT_Result WT_Text::materialize_obsolete_form(WT_Opcode const & opcode, WT_File & file)
{
WT_Integer16 tmp_int16;
WT_Integer32 tmp_int32;
switch (opcode.token()[0])
{
case 'x':
{
switch (m_stage)
{
case Getting_Started:
WD_Assert(!m_obsolete_font_holder);
m_obsolete_font_holder = new WT_Font;
if (!m_obsolete_font_holder)
return WT_Result::Out_Of_Memory_Error;
m_obsolete_font_holder->set_fields_defined( WT_Font::FONT_HEIGHT_BIT |
WT_Font::FONT_ROTATION_BIT |
WT_Font::FONT_OBLIQUE_BIT |
WT_Font::FONT_WIDTH_SCALE_BIT |
WT_Font::FONT_SPACING_BIT |
WT_Font::FONT_FLAGS_BIT );
m_stage = Getting_Width_Scale;
// No break
case Getting_Width_Scale:
WD_CHECK (file.read(tmp_int16));
m_obsolete_font_holder->width_scale().set(tmp_int16);
m_stage = Getting_Spacing;
case Getting_Spacing:
WD_CHECK (file.read(tmp_int16));
m_obsolete_font_holder->spacing().set(tmp_int16);
m_stage = Getting_Flags;
case Getting_Flags:
WD_CHECK (file.read(tmp_int32));
m_obsolete_font_holder->flags().set(tmp_int32);
m_stage = Getting_Oblique_Angle;
// No break
case Getting_Oblique_Angle:
WD_CHECK (file.read(tmp_int16));
m_obsolete_font_holder->oblique().set(tmp_int16);
m_stage = Getting_Overscore;
// No break
case Getting_Overscore:
WD_CHECK (m_option_overscore.materialize(*this, m_optioncode, file));
m_stage = Getting_Underscore;
// No break
case Getting_Underscore:
WD_CHECK (m_option_underscore.materialize(*this, m_optioncode, file));
m_stage = Getting_Rotation;
// No break
case Getting_Rotation:
WD_CHECK (file.read(tmp_int16));
m_obsolete_font_holder->rotation().set(tmp_int16);
m_stage = Getting_Height;
// No break
case Getting_Height:
WD_CHECK (file.read(tmp_int32));
if (file.heuristics().apply_transform())
tmp_int32 = (WT_Integer32) (tmp_int32 * file.heuristics().transform().m_y_scale);
m_obsolete_font_holder->height().set(tmp_int32);
m_stage = Getting_Position;
// No break
case Getting_Position:
WD_CHECK (file.read(1, &m_position));
m_stage = Getting_BBox_Deltas;
// No break
case Getting_BBox_Deltas:
{
WT_Logical_Point tmp_bbox[4];
WD_CHECK (file.read(4, tmp_bbox));
// convert from relative to absolute
m_position = file.de_update_current_point(m_position);
m_relativized = WD_False;
WT_Integer32 delta[8];
delta[0] = tmp_bbox[0].m_x;
delta[1] = tmp_bbox[0].m_y;
delta[2] = tmp_bbox[1].m_x;
delta[3] = tmp_bbox[1].m_y;
delta[4] = tmp_bbox[2].m_x;
delta[5] = tmp_bbox[2].m_y;
delta[6] = tmp_bbox[3].m_x;
delta[7] = tmp_bbox[3].m_y;
tmp_bbox[0].m_x = m_position.m_x + delta[4];
tmp_bbox[0].m_y = m_position.m_y + delta[6];
tmp_bbox[1].m_x = tmp_bbox[0].m_x + delta[7];
tmp_bbox[1].m_y = tmp_bbox[0].m_y + delta[5];
tmp_bbox[2].m_x = tmp_bbox[1].m_x + delta[2];
tmp_bbox[2].m_y = tmp_bbox[1].m_y + delta[3];
tmp_bbox[3].m_x = tmp_bbox[0].m_x + delta[0];
tmp_bbox[3].m_y = tmp_bbox[0].m_y + delta[1];
m_option_bounds.set(tmp_bbox);
m_stage = Getting_Str_Length;
}
// No break
case Getting_Str_Length:
WD_CHECK (file.read_count(m_obsolete_length_holder));
m_obsolete_msg_holder = new unsigned short[m_obsolete_length_holder + 1];
if (!m_obsolete_msg_holder)
throw WT_Result::Out_Of_Memory_Error;
m_stage = Getting_Msg;
// No break
case Getting_Msg:
WD_CHECK (file.read( 2 * m_obsolete_length_holder, (WT_Byte *)m_obsolete_msg_holder));
m_obsolete_msg_holder[m_obsolete_length_holder] = 0;
m_string.set(m_obsolete_length_holder, m_obsolete_msg_holder);
delete []m_obsolete_msg_holder;
m_stage = Completed;
break;
default:
return WT_Result::Internal_Error;
} // switch (m_stage)
if (file.heuristics().apply_transform())
transform(file.heuristics().transform());
} break;
case 0x18:
{
WT_Integer32 tmp_int32;
WT_Integer16 tmp_int16;
switch (m_stage)
{
case Getting_Started:
WD_Assert(!m_obsolete_font_holder);
m_obsolete_font_holder = new WT_Font;
if (!m_obsolete_font_holder)
return WT_Result::Out_Of_Memory_Error;
m_obsolete_font_holder->set_fields_defined( WT_Font::FONT_HEIGHT_BIT |
WT_Font::FONT_ROTATION_BIT );
m_stage = Getting_Rotation;
case Getting_Rotation:
WD_CHECK (file.read(tmp_int16));
m_obsolete_font_holder->rotation().set(tmp_int16);
m_stage = Getting_Height;
case Getting_Height:
WD_CHECK (file.read(tmp_int32));
if (file.heuristics().apply_transform())
tmp_int32 = (WT_Integer32) (tmp_int32 * file.heuristics().transform().m_y_scale);
m_obsolete_font_holder->height().set(tmp_int32);
m_stage = Getting_Position;
case Getting_Position:
WD_CHECK (file.read(1, &m_position));
m_relativized = WD_True;
m_stage = Getting_Str_Length;
case Getting_Str_Length:
WD_CHECK (file.read_count(m_obsolete_length_holder));
m_obsolete_msg_holder = new unsigned short[m_obsolete_length_holder + 1];
if (!m_obsolete_msg_holder)
throw WT_Result::Out_Of_Memory_Error;
m_stage = Getting_Msg;
// No break
case Getting_Msg:
WD_CHECK (file.read( 2 * m_obsolete_length_holder, (WT_Byte *)m_obsolete_msg_holder));
m_obsolete_msg_holder[m_obsolete_length_holder] = 0;
m_string.set(m_obsolete_length_holder, m_obsolete_msg_holder);
delete []m_obsolete_msg_holder;
m_stage = Completed;
break;
default:
return WT_Result::Internal_Error;
} // switch (m_stage)
} break;
default:
{
return WT_Result::Opcode_Not_Valid_For_This_Object;
} break;
} // switch
de_relativize(file);
if (file.heuristics().apply_transform())
transform(file.heuristics().transform());
m_materialized = WD_True;
// Now send these WT_Font attributes off for processing...
if (m_obsolete_font_holder)
{
m_obsolete_font_holder->process(file);
delete m_obsolete_font_holder;
m_obsolete_font_holder = WD_Null;
}
return WT_Result::Success;
}
///////////////////////////////////////////////////////////////////////////
WT_Result WT_Text::skip_operand(WT_Opcode const & opcode, WT_File & file)
{
switch (opcode.type())
{
case WT_Opcode::Single_Byte:
{
return materialize(opcode, file);
} 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_Text::transform(WT_Transform const & transform)
{
if (!m_transformed)
{
WT_Logical_Point tmp_pt;
tmp_pt = m_position;
m_position = tmp_pt * transform;
m_option_bounds.transform(transform);
m_transformed = WD_True;
}
}
///////////////////////////////////////////////////////////////////////////
WT_Result WT_Text::process(WT_File & file)
{
WD_Assert (file.text_action());
return (file.text_action())(*this, file);
}
WT_Result WT_Text::default_process(WT_Text &, WT_File &)
{
return WT_Result::Success;
}
///////////////////////////////////////////////////////////////////////////
#if DESIRED_CODE(WHIP_OUTPUT)
void WT_Text::relativize(WT_File & file)
{
if (!m_relativized)
{
m_position = file.update_current_point(m_position);
m_option_bounds.relativize(file);
m_relativized = WD_True;
} // If (!relativized)
}
#else
void WT_Text::relativize(WT_File &)
{
}
#endif // DESIRED_CODE()
///////////////////////////////////////////////////////////////////////////
void WT_Text::de_relativize(WT_File & file)
{
if (m_relativized)
{
m_position = file.de_update_current_point(m_position);
m_option_bounds.de_relativize(file);
m_relativized = WD_False;
} // If (!relativized)
}
///////////////////////////////////////////////////////////////////////////
// FIXME: WT_Text::update_bounds is completely Win32 specific, and must be ported.
#ifdef WD_WIN32_SYSTEM
#include <tchar.h>
#pragma comment (lib, "gdi32.lib") //for font bounds approximation
void WT_Text::update_bounds(WT_File * file)
{
if (m_option_bounds.bounds() != WD_Null)
{
WT_Drawable::update_bounds(m_option_bounds.bounds(), 2);
return;
}
WT_Drawable::update_bounds(m_position); //base point
if (m_string.length()==0)
return;
WT_Integer32 height = file->rendition().font().height();
int rotation = (int)((float)TWO_PI * (float)file->rendition().font().rotation() / 65536.0f);
int oblique = (int)((float)TWO_PI * (float)file->rendition().font().oblique() / 65536.0f);
BYTE charset = file->rendition().font().charset().charset();
BYTE pitch_and_family = file->rendition().font().pitch().pitch() | file->rendition().font().family().family();
UINT string_length = m_string.length();
BYTE italic = file->rendition().font().style().italic();
BYTE underline = file->rendition().font().style().underlined();
BYTE bold = file->rendition().font().style().bold();
//
// this is dangerous since it assumes wchar_t is always 16-bit uchar
//
wchar_t* facename = new wchar_t[file->rendition().font().font_name().name().length()+1];
const wchar_t* cwstr = (const wchar_t*)file->rendition().font().font_name().name().unicode();
if (cwstr)
{
wcscpy(facename, cwstr);
}
else
{
facename[0] = 0;
}
wchar_t* wstr = new wchar_t[m_string.length()+1];
wcscpy(wstr, (const wchar_t*)m_string.unicode());
HWND hwnd = NULL;
HDC hdc = NULL;
do
{
hwnd = ::GetDesktopWindow();
if (!hwnd || hwnd == INVALID_HANDLE_VALUE)
break;
hdc = ::GetDC(hwnd);
if (!hdc || hdc == INVALID_HANDLE_VALUE)
break;
LOGFONTW logfont;
logfont.lfHeight = 2048; //we'll get the right value down below
logfont.lfWidth = 0; //force aspect ratio of font
logfont.lfEscapement = oblique;
logfont.lfOrientation = rotation;
logfont.lfWeight = bold ? FW_BOLD : FW_DONTCARE;
logfont.lfItalic = italic;
logfont.lfUnderline = underline;
//logfont.lfStrikeOut;
logfont.lfCharSet = charset;
logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
logfont.lfQuality = DEFAULT_QUALITY;
logfont.lfPitchAndFamily = pitch_and_family;
memset(logfont.lfFaceName,0,LF_FACESIZE*sizeof(wchar_t));
wcsncpy(logfont.lfFaceName,facename,LF_FACESIZE);
HFONT hfont = ::CreateFontIndirectW(&logfont);
if (!hfont || hfont == INVALID_HANDLE_VALUE)
break;
//we want to get the width based on font design units, probably 2048, maybe 1024
//query and figure that out. use that as the height
HGDIOBJ hobj = ::SelectObject(hdc, hfont);
int size = ::GetOutlineTextMetricsW(hdc, 0, NULL);
if (size != 0)
{
OUTLINETEXTMETRICW *otm = (OUTLINETEXTMETRICW *)new char [size];
WD_Assert(otm != NULL);
UINT status = GetOutlineTextMetricsW (hdc, size, otm);
WD_Assert(status != 0);
if (status != 0)
logfont.lfHeight = otm->otmEMSquare;
delete [] otm;
}
else
{
logfont.lfHeight = 1000;
}
logfont.lfHeight *= -1; // Negative is more accurate
::SelectObject(hdc, hobj);
::DeleteObject(hfont);
hfont = ::CreateFontIndirectW(&logfont);
if (!hfont || hfont == INVALID_HANDLE_VALUE)
break;
hobj = ::SelectObject(hdc, hfont);
SIZE fontsize;
::GetTextExtentPointW(hdc, wstr, string_length, &fontsize);
::SelectObject(hdc, hobj);
::DeleteObject(hfont);
//now we have the width in font design units. Now translate this based on font height.
int deltaX = -(int)((double)height * (double)fontsize.cx / (double)logfont.lfHeight);
int deltaY = -(int)((double)height * (double)fontsize.cy / (double)logfont.lfHeight);
bool overflowX = (double)((m_position.m_x + deltaX) - (double)m_position.m_x) != deltaX;
bool overflowY = (double)((m_position.m_y + deltaY) - (double)m_position.m_y) != deltaY;
int ptx = overflowX //exceeded intmax?
? 0x7FFFFFFF
: m_position.m_x + deltaX;
int pty = overflowY //exceeded intmax?
? 0x7FFFFFFF
: m_position.m_y + deltaY;
// GetTextExtentPointW ignores rotation. So rotate around our basepoint ourselves
double drotation = ((float)TWO_PI * (float)file->rendition().font().rotation() / 65536.0f);
#define ROT(x,y) WT_Logical_Point(m_position.m_x+(long)((x)*cos((double)drotation)-(y)*sin((double)drotation)),\
m_position.m_y+(long)((y)*cos((double)drotation)+(x)*sin((double)drotation)))
ptx,pty;
WT_Logical_Point xx[] = { ROT(0,0),
ROT(deltaX,0),
ROT(deltaX,deltaY) ,
ROT(0,deltaY)};
// if (xx[0].m_x < 0 ||xx[1].m_x < 0 ||xx[2].m_x < 0 ||xx[3].m_x < 0)
// DebugBreak();
m_option_bounds.set(xx);
//m_option_bounds.transform(WT_Transform(m_position,1,1, 0));
WT_Drawable::update_bounds(m_option_bounds.bounds(), 4);
} while (false);
if (hdc && hdc != INVALID_HANDLE_VALUE && hwnd && hwnd != INVALID_HANDLE_VALUE)
::ReleaseDC(hwnd, hdc);
delete [] facename;
delete [] wstr;
}
#else // WD_WIN32_SYSTEM
void WT_Text::update_bounds(WT_File *) {
WD_Complain ("WT_Text::update_bounds is not implemented on this system");
}
#endif // WD_WIN32_SYSTEM

80
Whiptk702/transform.h Normal file
View File

@@ -0,0 +1,80 @@
// Copyright (c) 1996-2002 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.
//
#if !defined TRANSFORM_HEADER
#define TRANSFORM_HEADER
/// A simple transform providing translation, scaling, and simple 90, 180, 270 degree rotations.
/** \exception WT_Result::Toolkit_Usage_Error The rotation was not one of 0, 90, 180, 270.
*/
class WHIPTK_API WT_Transform
{
public:
WT_Logical_Point m_translate; /**< \brief Translation vector. */
double m_x_scale; /**< \brief X scale factor. */
double m_y_scale; /**< \brief Y scale factor. */
long m_rotation; /**< \brief Rotation (in degrees, one of 0, 90, 180, 270). */
/// Constructs a WT_Transform object.
WT_Transform()
: m_translate(0,0)
, m_x_scale(1.0)
, m_y_scale(1.0)
, m_rotation(0)
{ }
/// Constructs a WT_Transform object with the given data.
WT_Transform (
WT_Logical_Point trans, /**< Translation vector. */
double xval, /**< X scale factor. */
double yval, /**< Y scale factor. */
double rotation = 0.0 /**< Optional rotation (in degrees, one of 0, 90, 180, 270). */
)
: m_translate(trans)
, m_x_scale(xval)
, m_y_scale(yval)
{
set_rotation(rotation);
}
/// Sets the rotation value.
/** \exception WT_Result::Toolkit_Usage_Error The rotation was not one of 0, 90, 180, 270.
*/
void set_rotation(
double rotation /**< Rotation (in degrees, one of 0, 90, 180, 270). */
)
{
switch ((long)rotation)
{
case 0:
case 90:
case 180:
case 270:
m_rotation = (long)rotation;
break;
default:
m_rotation = (long)rotation;
//throw WT_Result::Toolkit_Usage_Error;
}
}
/// Returns the rotation value (in degrees, one of 0, 90, 180, 270).
long rotation() const
{ return m_rotation; }
};
#endif // TRANSFORM_HEADER