From 0b9083fc17ed419cc0005af1245edb5ff6a11ee4 Mon Sep 17 00:00:00 2001 From: Jos Groot Lipman Date: Tue, 12 Feb 2008 07:07:56 +0000 Subject: [PATCH] SLNKDWF 2.11 svn path=/Slnkdwf/trunk/; revision=12487 --- SlnkDWFCom/About.cpp | 15 + SlnkDWFCom/About.h | 1 + SlnkDWFCom/SLNKContour.cpp | 2 +- SlnkDWFCom/SLNKDWF.idl | 6 +- SlnkDWFCom/SLNKDWFVersion.h | 2 +- SlnkDWFCom/SLNKSymbol.cpp | 11 + SlnkDWFCom/SLNKSymbolDefImpl.cpp | 14 +- SlnkDWFCom/SLNKSymbolDefImpl.h | 2 +- SlnkDWFCom/SLNKSymbolImpl.cpp | 15 +- SlnkDWFCom/SLNKSymbolImpl.h | 2 + SlnkDWFCom/WhipFile.cpp | 14 +- SlnkDWFCom/slnksymbol.h | 1 + SlnkDWFImpl/SLNKContourImpl.cpp | 112 ++-- SlnkDWFImpl/SLNKContourImpl.h | 3 +- SlnkDWFImpl/Whip2DCImpl.cpp | 29 +- SlnkDWFImpl/Whip2DCState.h | 1 + Whiptk702/.gitignore | 0 Whiptk702/ellipse.cpp | 720 ++++++++++++++++++++ Whiptk702/font_options.cpp | 1065 ++++++++++++++++++++++++++++++ Whiptk702/logical_point.cpp | 99 +++ Whiptk702/text.cpp | 855 ++++++++++++++++++++++++ Whiptk702/transform.h | 80 +++ 22 files changed, 2974 insertions(+), 75 deletions(-) delete mode 100644 Whiptk702/.gitignore create mode 100644 Whiptk702/ellipse.cpp create mode 100644 Whiptk702/font_options.cpp create mode 100644 Whiptk702/logical_point.cpp create mode 100644 Whiptk702/text.cpp create mode 100644 Whiptk702/transform.h diff --git a/SlnkDWFCom/About.cpp b/SlnkDWFCom/About.cpp index 0565d49..5c1f948 100644 --- a/SlnkDWFCom/About.cpp +++ b/SlnkDWFCom/About.cpp @@ -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; +} diff --git a/SlnkDWFCom/About.h b/SlnkDWFCom/About.h index f1dadc5..74f1704 100644 --- a/SlnkDWFCom/About.h +++ b/SlnkDWFCom/About.h @@ -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) diff --git a/SlnkDWFCom/SLNKContour.cpp b/SlnkDWFCom/SLNKContour.cpp index 68e25a1..58e9e86 100644 --- a/SlnkDWFCom/SLNKContour.cpp +++ b/SlnkDWFCom/SLNKContour.cpp @@ -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; diff --git a/SlnkDWFCom/SLNKDWF.idl b/SlnkDWFCom/SLNKDWF.idl index 8e624f9..65b9e13 100644 --- a/SlnkDWFCom/SLNKDWF.idl +++ b/SlnkDWFCom/SLNKDWF.idl @@ -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, diff --git a/SlnkDWFCom/SLNKDWFVersion.h b/SlnkDWFCom/SLNKDWFVersion.h index fe5e906..8cf4b80 100644 --- a/SlnkDWFCom/SLNKDWFVersion.h +++ b/SlnkDWFCom/SLNKDWFVersion.h @@ -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 diff --git a/SlnkDWFCom/SLNKSymbol.cpp b/SlnkDWFCom/SLNKSymbol.cpp index 5dd2e8e..4869261 100644 --- a/SlnkDWFCom/SLNKSymbol.cpp +++ b/SlnkDWFCom/SLNKSymbol.cpp @@ -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; +} diff --git a/SlnkDWFCom/SLNKSymbolDefImpl.cpp b/SlnkDWFCom/SLNKSymbolDefImpl.cpp index d0ff0a5..6114966 100644 --- a/SlnkDWFCom/SLNKSymbolDefImpl.cpp +++ b/SlnkDWFCom/SLNKSymbolDefImpl.cpp @@ -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) { diff --git a/SlnkDWFCom/SLNKSymbolDefImpl.h b/SlnkDWFCom/SLNKSymbolDefImpl.h index 4a02864..ceaef9f 100644 --- a/SlnkDWFCom/SLNKSymbolDefImpl.h +++ b/SlnkDWFCom/SLNKSymbolDefImpl.h @@ -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: diff --git a/SlnkDWFCom/SLNKSymbolImpl.cpp b/SlnkDWFCom/SLNKSymbolImpl.cpp index 9b0b61f..ef46b39 100644 --- a/SlnkDWFCom/SLNKSymbolImpl.cpp +++ b/SlnkDWFCom/SLNKSymbolImpl.cpp @@ -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 } diff --git a/SlnkDWFCom/SLNKSymbolImpl.h b/SlnkDWFCom/SLNKSymbolImpl.h index 60cd114..f8acd99 100644 --- a/SlnkDWFCom/SLNKSymbolImpl.h +++ b/SlnkDWFCom/SLNKSymbolImpl.h @@ -24,4 +24,6 @@ public: int m_Rotation; double m_Scale; CSLNKContourImpl m_SLNKContour; + WT_Color m_Color; + BOOL m_ColorSet; }; diff --git a/SlnkDWFCom/WhipFile.cpp b/SlnkDWFCom/WhipFile.cpp index ae99193..74dce4a 100644 --- a/SlnkDWFCom/WhipFile.cpp +++ b/SlnkDWFCom/WhipFile.cpp @@ -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; im_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; im_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; i1 P is on the forward extension of AB 00 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]; diff --git a/SlnkDWFImpl/SLNKContourImpl.h b/SlnkDWFImpl/SLNKContourImpl.h index 4293b69..28d0184 100644 --- a/SlnkDWFImpl/SLNKContourImpl.h +++ b/SlnkDWFImpl/SLNKContourImpl.h @@ -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; diff --git a/SlnkDWFImpl/Whip2DCImpl.cpp b/SlnkDWFImpl/Whip2DCImpl.cpp index 42f9eca..2dcf703 100644 --- a/SlnkDWFImpl/Whip2DCImpl.cpp +++ b/SlnkDWFImpl/Whip2DCImpl.cpp @@ -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); } diff --git a/SlnkDWFImpl/Whip2DCState.h b/SlnkDWFImpl/Whip2DCState.h index 2518355..b5b4a9f 100644 --- a/SlnkDWFImpl/Whip2DCState.h +++ b/SlnkDWFImpl/Whip2DCState.h @@ -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; diff --git a/Whiptk702/.gitignore b/Whiptk702/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/Whiptk702/ellipse.cpp b/Whiptk702/ellipse.cpp new file mode 100644 index 0000000..9156ea8 --- /dev/null +++ b/Whiptk702/ellipse.cpp @@ -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; +} diff --git a/Whiptk702/font_options.cpp b/Whiptk702/font_options.cpp new file mode 100644 index 0000000..20d1f61 --- /dev/null +++ b/Whiptk702/font_options.cpp @@ -0,0 +1,1065 @@ +// 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/font_options.cpp 3 5/09/05 12:39a Evansg $ + + +#include "whiptk/pch.h" +#include + +/////////////////////////////////////////////////////////////////////////// +#if DESIRED_CODE(WHIP_OUTPUT) +WT_Result WT_Font_Option_Font_Name::serialize(WT_Object const &, WT_File & file) const +{ + if (file.heuristics().allow_binary_data()) + return m_font_name.serialize(file,WD_True); + + // ASCII output + WD_CHECK (file.write(" (Name ")); + WD_CHECK (m_font_name.serialize(file)); + return file.write((WT_Byte) ')'); +} +#else +WT_Result WT_Font_Option_Font_Name::serialize(WT_Object const &, WT_File &) const +{ + return WT_Result::Success; +} +#endif // DESIRED_CODE() + +/////////////////////////////////////////////////////////////////////////// +WT_Result WT_Font_Option_Font_Name::materialize(WT_Object &, WT_Optioncode const & optioncode, WT_File & file) +{ + switch (m_stage) + { + case Getting_Operand: + WD_CHECK (m_font_name.materialize(file)); + m_materialized = WD_True; + + if (optioncode.type() == WT_Opcode::Extended_ASCII) + m_stage = Getting_Close_Paren; // ASCII + else + return WT_Result::Success; // Binary + + // No break + case Getting_Close_Paren: + + WD_CHECK(optioncode.skip_past_matching_paren(file)); + m_stage = Completed; + break; + + default: + WD_Assert(WD_False); + return WT_Result::Internal_Error; + + } // switch (m_stage) + + return WT_Result::Success; +} + +/////////////////////////////////////////////////////////////////////////// +#if DESIRED_CODE(WHIP_OUTPUT) +WT_Result WT_Font_Option_Charset::serialize(WT_Object const &, WT_File & file) const +{ + if (file.heuristics().allow_binary_data()) + { + WD_CHECK (file.write((WT_Byte) m_charset)); + } + else + { // ASCII output + + WD_CHECK (file.write(" (Charset ")); + switch (m_charset) + { + case CHARSET_ANSI: + WD_CHECK (file.write("ANSI)")); + break; + case CHARSET_DEFAULT: + WD_CHECK (file.write("DEFAULT)")); + break; + case CHARSET_SYMBOL: + WD_CHECK (file.write("SYMBOL)")); + break; + case CHARSET_MAC: + WD_CHECK (file.write("MAC)")); + break; + case CHARSET_UNICODE: + WD_CHECK (file.write("UNICODE)")); + break; + case CHARSET_SHIFTJIS: + WD_CHECK (file.write("SHIFTJIS)")); + break; + case CHARSET_HANGEUL: + WD_CHECK (file.write("HANGEUL)")); + break; + case CHARSET_JOHAB: + WD_CHECK (file.write("JOHAB)")); + break; + case CHARSET_GB2312: + WD_CHECK (file.write("GB2312)")); + break; + case CHARSET_CHINESEBIG5: + WD_CHECK (file.write("CHINESEBIG5)")); + break; + case CHARSET_GREEK: + WD_CHECK (file.write("GREEK)")); + break; + case CHARSET_TURKISH: + WD_CHECK (file.write("TURKISH)")); + break; + case CHARSET_VIETNAMESE: + WD_CHECK (file.write("VIETNAMESE)")); + break; + case CHARSET_HEBREW: + WD_CHECK (file.write("HEBREW)")); + break; + case CHARSET_ARABIC: + WD_CHECK (file.write("ARABIC)")); + break; + case CHARSET_BALTIC: + WD_CHECK (file.write("BALTIC)")); + break; + case CHARSET_RUSSIAN: + WD_CHECK (file.write("RUSSIAN)")); + break; + case CHARSET_THAI: + WD_CHECK (file.write("THAI)")); + break; + case CHARSET_EASTEUROPE: + WD_CHECK (file.write("EASTEUROPE)")); + break; + case CHARSET_OEM: + WD_CHECK (file.write("OEM)")); + break; + + default: + WD_CHECK (file.write_ascii((WT_Integer32) m_charset)); + WD_CHECK (file.write((WT_Byte)')')); + + } // switch (m_charset) + } // else ASCII output + + return WT_Result::Success; +} +#else +WT_Result WT_Font_Option_Charset::serialize(WT_Object const &, WT_File &) const +{ + return WT_Result::Success; +} +#endif // DESIRED_CODE() + +/////////////////////////////////////////////////////////////////////////// +WT_Result WT_Font_Option_Charset::materialize(WT_Object &, WT_Optioncode const & optioncode, WT_File & file) +{ + if (optioncode.type() != WT_Opcode::Extended_ASCII) + { + // Binary + WD_CHECK(file.read(m_charset)); + } + else + { + switch (m_stage) + { + case Getting_Operand: + char * operand; + + WD_CHECK(file.read(operand, 80)); + + if (!strcmp("ANSI", operand)) + m_charset = CHARSET_ANSI; + else if (!strcmp("DEFAULT", operand)) + m_charset = CHARSET_DEFAULT; + else if (!strcmp("SYMBOL", operand)) + m_charset = CHARSET_SYMBOL; + else if (!strcmp("MAC", operand)) + m_charset = CHARSET_MAC; + else if (!strcmp("UNICODE", operand)) + m_charset = CHARSET_UNICODE; + else if (!strcmp("SHIFTJIS", operand)) + m_charset = CHARSET_SHIFTJIS; + else if (!strcmp("HANGEUL", operand)) + m_charset = CHARSET_HANGEUL; + else if (!strcmp("JOHAB", operand)) + m_charset = CHARSET_JOHAB; + else if (!strcmp("GB2312", operand)) + m_charset = CHARSET_GB2312; + else if (!strcmp("CHINESEBIG5", operand)) + m_charset = CHARSET_CHINESEBIG5; + else if (!strcmp("GREEK", operand)) + m_charset = CHARSET_GREEK; + else if (!strcmp("TURKISH", operand)) + m_charset = CHARSET_TURKISH; + else if (!strcmp("VIETNAMESE", operand)) + m_charset = CHARSET_VIETNAMESE; + else if (!strcmp("HEBREW", operand)) + m_charset = CHARSET_HEBREW; + else if (!strcmp("ARABIC", operand)) + m_charset = CHARSET_ARABIC; + else if (!strcmp("BALTIC", operand)) + m_charset = CHARSET_BALTIC; + else if (!strcmp("RUSSIAN", operand)) + m_charset = CHARSET_RUSSIAN; + else if (!strcmp("THAI", operand)) + m_charset = CHARSET_THAI; + else if (!strcmp("EASTEUROPE", operand)) + m_charset = CHARSET_EASTEUROPE; + else if (!strcmp("OEM", operand)) + m_charset = CHARSET_OEM; + else + { + int tmp = atoi(operand); + if (tmp < 0 || tmp > 0xFF) + { + delete []operand; + return WT_Result::Corrupt_File_Error; + } + + m_charset = (WT_Byte) tmp; + } + + delete []operand; + m_stage = Getting_Close_Paren; + + // No break + case Getting_Close_Paren: + + WD_CHECK(optioncode.skip_past_matching_paren(file)); + m_stage = Completed; + break; + + default: + WD_Assert(WD_False); + return WT_Result::Internal_Error; + + } // switch (m_stage) + } // else (extended_ASCII) + + m_materialized = WD_True; + return WT_Result::Success; +} + +/////////////////////////////////////////////////////////////////////////// +#if DESIRED_CODE(WHIP_OUTPUT) +WT_Result WT_Font_Option_Pitch::serialize(WT_Object const &, WT_File & file) const +{ + if (file.heuristics().allow_binary_data()) + { + return file.write(m_pitch); + } + else + { // ASCII output + + WD_CHECK (file.write(" (Pitch ")); + switch (m_pitch) + { + case PITCH_DEFAULT: + WD_CHECK (file.write("default)")); + break; + case PITCH_FIXED: + WD_CHECK (file.write("fixed)")); + break; + case PITCH_VARIABLE: + WD_CHECK (file.write("variable)")); + break; + default: + return WT_Result::Internal_Error; + } // switch on pitch + } // else ASCII + + return WT_Result::Success; +} +#else +WT_Result WT_Font_Option_Pitch::serialize(WT_Object const &, WT_File &) const +{ + return WT_Result::Success; +} +#endif // DESIRED_CODE() + + +/////////////////////////////////////////////////////////////////////////// +WT_Result WT_Font_Option_Pitch::materialize(WT_Object &, WT_Optioncode const & optioncode, WT_File & file) +{ + if (optioncode.type() != WT_Opcode::Extended_ASCII) + { + WD_CHECK (file.read(m_pitch)); + } + else + { + switch (m_stage) + { + case Getting_Operand: + char * operand; + + WD_CHECK(file.read(operand, 80)); + + if (!strcmp("default", operand)) + m_pitch = PITCH_DEFAULT; + else if (!strcmp("fixed", operand)) + m_pitch = PITCH_FIXED; + else if (!strcmp("variable", operand)) + m_pitch = PITCH_VARIABLE; + else + { + int tmp = atoi(operand); + if (tmp < 0 || tmp > 0xFF) + { + delete []operand; + return WT_Result::Corrupt_File_Error; + } + + m_pitch = (WT_Byte) tmp; + } + + delete []operand; + m_stage = Getting_Close_Paren; + + // No break + case Getting_Close_Paren: + + WD_CHECK(optioncode.skip_past_matching_paren(file)); + m_stage = Completed; + break; + + default: + WD_Assert(WD_False); + return WT_Result::Internal_Error; + + } // switch (m_stage) + } // else (ascii) + + m_materialized = WD_True; + return WT_Result::Success; +} + +/////////////////////////////////////////////////////////////////////////// +#if DESIRED_CODE(WHIP_OUTPUT) +WT_Result WT_Font_Option_Family::serialize(WT_Object const &, WT_File & file) const +{ + if (file.heuristics().allow_binary_data()) + { + return file.write(m_family); + } + else + { // ASCII output + + WD_CHECK (file.write(" (Family ")); + switch (m_family) + { + case FAMILY_DECORATIVE: + WD_CHECK (file.write("decorative)")); + break; + case FAMILY_UNKNOWN: + WD_CHECK (file.write("unknown)")); + break; + case FAMILY_MODERN: + WD_CHECK (file.write("modern)")); + break; + case FAMILY_ROMAN: + WD_CHECK (file.write("roman)")); + break; + case FAMILY_SCRIPT: + WD_CHECK (file.write("script)")); + break; + case FAMILY_SWISS: + WD_CHECK (file.write("swiss)")); + break; + default: + return WT_Result::Internal_Error; + } // switch on family + } // else ASCII + + return WT_Result::Success; +} +#else +WT_Result WT_Font_Option_Family::serialize(WT_Object const &, WT_File &) const +{ + return WT_Result::Success; +} +#endif // DESIRED_CODE() + +/////////////////////////////////////////////////////////////////////////// +WT_Result WT_Font_Option_Family::materialize(WT_Object &, WT_Optioncode const & optioncode, WT_File & file) +{ + if (optioncode.type() != WT_Opcode::Extended_ASCII) + { + WD_CHECK (file.read(m_family)); + } + else + { + switch (m_stage) + { + case Getting_Operand: + char * operand; + + WD_CHECK(file.read(operand, 80)); + + if (!strcmp("decorative", operand)) + m_family = FAMILY_DECORATIVE; + else if (!strcmp("unknown", operand)) + m_family = FAMILY_UNKNOWN; + else if (!strcmp("modern", operand)) + m_family = FAMILY_MODERN; + else if (!strcmp("roman", operand)) + m_family = FAMILY_ROMAN; + else if (!strcmp("script", operand)) + m_family = FAMILY_SCRIPT; + else if (!strcmp("swiss", operand)) + m_family = FAMILY_SWISS; + else + { + int tmp = atoi(operand); + if (tmp < 0 || tmp > 0xFF) + { + delete []operand; + return WT_Result::Corrupt_File_Error; + } + + m_family = (WT_Byte) tmp; + } + + delete []operand; + m_stage = Getting_Close_Paren; + + // No break + case Getting_Close_Paren: + + WD_CHECK(optioncode.skip_past_matching_paren(file)); + m_stage = Completed; + break; + + default: + WD_Assert(WD_False); + return WT_Result::Internal_Error; + + } // switch (m_stage) + } // else (ascii) + + m_materialized = WD_True; + return WT_Result::Success; +} + +/////////////////////////////////////////////////////////////////////////// +#if DESIRED_CODE(WHIP_OUTPUT) +WT_Result WT_Font_Option_Style::serialize(WT_Object const &, WT_File & file) const +{ + if (file.heuristics().allow_binary_data()) + { + // Binary + WT_Byte style = (m_bold ? WD_FONT_STYLE_BOLD : 0x00) + + (m_italic ? WD_FONT_STYLE_ITALIC : 0x00) + + (m_underlined ? WD_FONT_STYLE_UNDERLINED : 0x00); + + return file.write(style); + } + else + { // ASCII output + + WD_CHECK (file.write(" (Style")); + if (m_bold) + WD_CHECK (file.write(" bold")); + if (m_italic) + WD_CHECK (file.write(" italic")); + if (m_underlined) + WD_CHECK (file.write(" underlined")); + + WD_CHECK (file.write((WT_Byte)')')); + } // else ASCII + + return WT_Result::Success; +} +#else +WT_Result WT_Font_Option_Style::serialize(WT_Object const &, WT_File &) const +{ + return WT_Result::Success; +} +#endif // DESIRED_CODE() + +/////////////////////////////////////////////////////////////////////////// +WT_Result WT_Font_Option_Style::materialize(WT_Object &, WT_Optioncode const & optioncode, WT_File & file) +{ + if (optioncode.type() != WT_Opcode::Extended_ASCII) + { + WT_Byte style; + + WD_CHECK (file.read(style)); + if (style & WD_FONT_STYLE_BOLD) + m_bold = WD_True; + else + m_bold = WD_False; + + if (style & WD_FONT_STYLE_ITALIC) + m_italic = WD_True; + else + m_italic = WD_False; + + if (style & WD_FONT_STYLE_UNDERLINED) + m_underlined = WD_True; + else + m_underlined = WD_False; + } + else + { + switch (m_stage) + { + case Starting: + m_bold = WD_False; + m_italic = WD_False; + m_underlined = WD_False; + m_stage = Getting_Next_Optioncode; + + // No break +Getting_Next_Optioncode_Hop: + case Getting_Next_Optioncode: + + WD_CHECK(m_optioncode.get_opcode(file, WD_True)); + + switch (m_optioncode.type()) + { + + case WT_Opcode::Extended_ASCII: + m_stage = Skipping_Optioncode; + goto Skipping_Optioncode_Hop; + + + case WT_Opcode::Unary_Optioncode: + if (!strcmp((const char *)m_optioncode.token(), "bold")) + m_bold = WD_True; + else if (!strcmp((const char *)m_optioncode.token(), "italic")) + m_italic = WD_True; + else if (!strcmp((const char *)m_optioncode.token(), "underlined")) + m_underlined = WD_True; + goto Getting_Next_Optioncode_Hop; + + case WT_Opcode::Null_Optioncode: + m_stage = Getting_Close_Paren; + break; + default: + return WT_Result::Corrupt_File_Error; + } // switch + + // No Break; + case Getting_Close_Paren: + WD_CHECK(optioncode.skip_past_matching_paren(file)); + m_stage = Completed; + break; + +Skipping_Optioncode_Hop: + case Skipping_Optioncode: + WD_CHECK(m_optioncode.skip_past_matching_paren(file)); + goto Getting_Next_Optioncode_Hop; + + + default: + WD_Assert(WD_False); + return WT_Result::Internal_Error; + + } // switch (m_stage) + } // else (ascii) + + m_materialized = WD_True; + return WT_Result::Success; +} + +/////////////////////////////////////////////////////////////////////////// +#if DESIRED_CODE(WHIP_OUTPUT) +WT_Result WT_Font_Option_Height::serialize(WT_Object const &, WT_File & file) const +{ + WT_Integer32 adjusted_height; + + if (file.heuristics().apply_transform()) + // TODO: does this make sense if we are doing Landscape flipping? + adjusted_height = (long)(height() * file.heuristics().transform().m_y_scale); + else + adjusted_height = height(); + + if (adjusted_height < 0) + adjusted_height = - adjusted_height; + + if (file.heuristics().allow_binary_data()) + { + // Binary + return file.write(adjusted_height); + } + else + { // ASCII output + + WD_CHECK (file.write(" (Height ")); + WD_CHECK (file.write_ascii(adjusted_height)); + WD_CHECK (file.write((WT_Byte)')')); + } // else ASCII + + return WT_Result::Success; +} +#else +WT_Result WT_Font_Option_Height::serialize(WT_Object const &, WT_File &) const +{ + return WT_Result::Success; +} +#endif // DESIRED_CODE() + +/////////////////////////////////////////////////////////////////////////// +WT_Result WT_Font_Option_Height::materialize(WT_Object &, WT_Optioncode const & optioncode, WT_File & file) +{ + WT_Integer32 height = 0; + + if (optioncode.type() != WT_Opcode::Extended_ASCII) + { + WD_CHECK (file.read(height)); + } + else + { + switch (m_stage) + { + case Getting_Operand: + WD_CHECK(file.read_ascii(height)); + m_stage = Getting_Close_Paren; + + // No break + case Getting_Close_Paren: + + WD_CHECK(optioncode.skip_past_matching_paren(file)); + m_stage = Completed; + break; + + default: + WD_Assert(WD_False); + return WT_Result::Internal_Error; + + } // switch (m_stage) + } + + if (file.heuristics().apply_transform()) + // TODO: Does this make sense if we are doing Landscape flipping? + m_height = (WT_Integer32)(height * file.heuristics().transform().m_y_scale); + else + m_height = height; + + m_materialized = WD_True; + return WT_Result::Success; +} + +/////////////////////////////////////////////////////////////////////////// +#if DESIRED_CODE(WHIP_OUTPUT) +WT_Result WT_Font_Option_Rotation::serialize(WT_Object const &, WT_File & file) const +{ + + WT_Unsigned_Integer16 fixed_rot = rotation(); + + if(file.heuristics().apply_transform()) { + fixed_rot = (WT_Unsigned_Integer16)( + (WT_Unsigned_Integer16) + ( (long)rotation() + + (long)WD_90_DEGREES_AS_SHORT * ((double)file.heuristics().transform().rotation() / 90) + ) & 0x0000FFFF); + } + + if (file.heuristics().allow_binary_data()) + { + // Binary + return file.write(fixed_rot); + } + else + { // ASCII output + + WD_CHECK (file.write(" (Rotation ")); + WD_CHECK (file.write_ascii(fixed_rot)); + WD_CHECK (file.write((WT_Byte)')')); + } // else ASCII + + return WT_Result::Success; +} +#else +WT_Result WT_Font_Option_Rotation::serialize(WT_Object const &, WT_File &) const +{ + return WT_Result::Success; +} +#endif // DESIRED_CODE() + +/////////////////////////////////////////////////////////////////////////// +WT_Result WT_Font_Option_Rotation::materialize(WT_Object &, WT_Optioncode const & optioncode, WT_File & file) +{ + if (optioncode.type() != WT_Opcode::Extended_ASCII) + { + WD_CHECK (file.read(m_rotation)); + } + else + { + switch (m_stage) + { + case Getting_Operand: + WD_CHECK(file.read_ascii(m_rotation)); + m_stage = Getting_Close_Paren; + + // No break + case Getting_Close_Paren: + + WD_CHECK(optioncode.skip_past_matching_paren(file)); + m_stage = Completed; + break; + + default: + WD_Assert(WD_False); + return WT_Result::Internal_Error; + + } // switch (m_stage) + } // else (ascii) + + if (file.heuristics().apply_transform()) + { + //transform(file.heuristics().transform()); + m_rotation = (WT_Unsigned_Integer16)( + (WT_Unsigned_Integer16) + ( (long)m_rotation + + (long)WD_90_DEGREES_AS_SHORT * ((double)file.heuristics().transform().rotation() / 90) + ) & 0x0000FFFF); + } + + m_materialized = WD_True; + return WT_Result::Success; +} + +/////////////////////////////////////////////////////////////////////////// +#if DESIRED_CODE(WHIP_OUTPUT) +WT_Result WT_Font_Option_Width_Scale::serialize(WT_Object const &, WT_File & file) const +{ + if (file.heuristics().allow_binary_data()) + { + // Binary + return file.write(width_scale()); + } + else + { // ASCII output + + WD_CHECK (file.write(" (Widthscale ")); + WD_CHECK (file.write_ascii(m_width_scale)); + WD_CHECK (file.write((WT_Byte)')')); + } // else ASCII + + return WT_Result::Success; +} + +#else +WT_Result WT_Font_Option_Width_Scale::serialize(WT_Object const &, WT_File &) const +{ + return WT_Result::Success; +} +#endif // DESIRED_CODE() + +/////////////////////////////////////////////////////////////////////////// +WT_Result WT_Font_Option_Width_Scale::materialize(WT_Object &, WT_Optioncode const & optioncode, WT_File & file) +{ + if (optioncode.type() != WT_Opcode::Extended_ASCII) + { + WD_CHECK (file.read(m_width_scale)); + } + else + { + switch (m_stage) + { + case Getting_Operand: + WD_CHECK(file.read_ascii(m_width_scale)); + m_stage = Getting_Close_Paren; + + // No break + case Getting_Close_Paren: + + WD_CHECK(optioncode.skip_past_matching_paren(file)); + m_stage = Completed; + break; + + default: + WD_Assert(WD_False); + return WT_Result::Internal_Error; + + } // switch (m_stage) + } // else (ascii) + + m_materialized = WD_True; + return WT_Result::Success; +} + +/////////////////////////////////////////////////////////////////////////// +#if DESIRED_CODE(WHIP_OUTPUT) +WT_Result WT_Font_Option_Spacing::serialize(WT_Object const &, WT_File & file) const +{ + if (file.heuristics().allow_binary_data()) + { + // Binary + return file.write(spacing()); + } + else + { // ASCII output + + WD_CHECK (file.write(" (Spacing ")); + WD_CHECK (file.write_ascii(m_spacing)); + WD_CHECK (file.write((WT_Byte)')')); + } // else ASCII + + return WT_Result::Success; +} +#else +WT_Result WT_Font_Option_Spacing::serialize(WT_Object const &, WT_File &) const +{ + return WT_Result::Success; +} +#endif // DESIRED_CODE() + +/////////////////////////////////////////////////////////////////////////// +WT_Result WT_Font_Option_Spacing::materialize(WT_Object &, WT_Optioncode const & optioncode, WT_File & file) +{ + if (optioncode.type() != WT_Opcode::Extended_ASCII) + { + WD_CHECK (file.read(m_spacing)); + } + else + { + switch (m_stage) + { + case Getting_Operand: + WD_CHECK(file.read_ascii(m_spacing)); + m_stage = Getting_Close_Paren; + + // No break + case Getting_Close_Paren: + + WD_CHECK(optioncode.skip_past_matching_paren(file)); + m_stage = Completed; + break; + + default: + WD_Assert(WD_False); + return WT_Result::Internal_Error; + + } // switch (m_stage) + } // else (ascii) + + m_materialized = WD_True; + return WT_Result::Success; +} + +/////////////////////////////////////////////////////////////////////////// +#if DESIRED_CODE(WHIP_OUTPUT) +WT_Result WT_Font_Option_Oblique::serialize(WT_Object const &, WT_File & file) const +{ + if (file.heuristics().allow_binary_data()) + { + // Binary + return file.write(oblique()); + } + else + { // ASCII output + + WD_CHECK (file.write(" (Oblique ")); + WD_CHECK (file.write_ascii(m_oblique)); + WD_CHECK (file.write((WT_Byte)')')); + } // else ASCII + + return WT_Result::Success; +} +#else +WT_Result WT_Font_Option_Oblique::serialize(WT_Object const &, WT_File &) const +{ + return WT_Result::Success; +} +#endif // DESIRED_CODE() + +/////////////////////////////////////////////////////////////////////////// +WT_Result WT_Font_Option_Oblique::materialize(WT_Object &, WT_Optioncode const & optioncode, WT_File & file) +{ + if (optioncode.type() != WT_Opcode::Extended_ASCII) + { + WD_CHECK (file.read(m_oblique)); + } + else + { + switch (m_stage) + { + case Getting_Operand: + WD_CHECK(file.read_ascii(m_oblique)); + m_stage = Getting_Close_Paren; + + // No break + case Getting_Close_Paren: + + WD_CHECK(optioncode.skip_past_matching_paren(file)); + m_stage = Completed; + break; + + default: + WD_Assert(WD_False); + return WT_Result::Internal_Error; + + } // switch (m_stage) + } // else (ascii) + + m_materialized = WD_True; + return WT_Result::Success; +} + +/////////////////////////////////////////////////////////////////////////// +#if DESIRED_CODE(WHIP_OUTPUT) +WT_Result WT_Font_Option_Flags::serialize(WT_Object const &, WT_File & file) const +{ + if (file.heuristics().allow_binary_data()) + { + // Binary + return file.write(flags()); + } + else + { // ASCII output + + WD_CHECK (file.write(" (Flags ")); + WD_CHECK (file.write_ascii(m_flags)); + WD_CHECK (file.write((WT_Byte)')')); + } // else ASCII + + return WT_Result::Success; +} +#else +WT_Result WT_Font_Option_Flags::serialize(WT_Object const &, WT_File &) const +{ + return WT_Result::Success; +} +#endif // DESIRED_CODE() + +/////////////////////////////////////////////////////////////////////////// +WT_Result WT_Font_Option_Flags::materialize(WT_Object &, WT_Optioncode const & optioncode, WT_File & file) +{ + if (optioncode.type() != WT_Opcode::Extended_ASCII) + { + WD_CHECK (file.read(m_flags)); + } + else + { + switch (m_stage) + { + case Getting_Operand: + WD_CHECK(file.read_ascii(m_flags)); + m_stage = Getting_Close_Paren; + + // No break + case Getting_Close_Paren: + + WD_CHECK(optioncode.skip_past_matching_paren(file)); + m_stage = Completed; + break; + + default: + WD_Assert(WD_False); + return WT_Result::Internal_Error; + + } // switch (m_stage) + } // else (ascii) + + m_materialized = WD_True; + return WT_Result::Success; +} + +/////////////////////////////////////////////////////////////////////////// +int WT_Font_Optioncode::option_id_from_optioncode() +{ + if (!strcmp((char const *)token(), "(Name")) + m_option_id = Font_Name_Option; + else if (!strcmp((char const *)token(), "(Charset")) + m_option_id = Charset_Option; + else if (!strcmp((char const *)token(), "(Pitch")) + m_option_id = Pitch_Option; + else if (!strcmp((char const *)token(), "(Family")) + m_option_id = Family_Option; + else if (!strcmp((char const *)token(), "(Style")) + m_option_id = Style_Option; + else if (!strcmp((char const *)token(), "(Height")) + m_option_id = Height_Option; + else if (!strcmp((char const *)token(), "(Rotation")) + m_option_id = Rotation_Option; + else if (!strcmp((char const *)token(), "(Widthscale")) + m_option_id = Width_Scale_Option; + else if (!strcmp((char const *)token(), "(Spacing")) + m_option_id = Spacing_Option; + else if (!strcmp((char const *)token(), "(Oblique")) + m_option_id = Oblique_Option; + else if (!strcmp((char const *)token(), "(Flags")) + m_option_id = Flags_Option; + else + m_option_id = Unknown_Option; + + return m_option_id; +} + +/////////////////////////////////////////////////////////////////////////// +WT_Object::WT_ID WT_Font_Option_Font_Name::object_id() const +{ + return WT_Object::Font_Option_Font_Name_ID; +} + +/////////////////////////////////////////////////////////////////////////// +WT_Object::WT_ID WT_Font_Option_Charset::object_id() const +{ + return WT_Object::Font_Option_Charset_ID; +} + +/////////////////////////////////////////////////////////////////////////// +WT_Object::WT_ID WT_Font_Option_Pitch::object_id() const +{ + return WT_Object::Font_Option_Pitch_ID; +} + +/////////////////////////////////////////////////////////////////////////// +WT_Object::WT_ID WT_Font_Option_Family::object_id() const +{ + return WT_Object::Font_Option_Family_ID; +} + +/////////////////////////////////////////////////////////////////////////// +WT_Object::WT_ID WT_Font_Option_Style::object_id() const +{ + return WT_Object::Font_Option_Style_ID; +} + +/////////////////////////////////////////////////////////////////////////// +WT_Object::WT_ID WT_Font_Option_Height::object_id() const +{ + return WT_Object::Font_Option_Height_ID; +} + +/////////////////////////////////////////////////////////////////////////// +WT_Object::WT_ID WT_Font_Option_Rotation::object_id() const +{ + return WT_Object::Font_Option_Rotation_ID; +} + +/////////////////////////////////////////////////////////////////////////// +WT_Object::WT_ID WT_Font_Option_Width_Scale::object_id() const +{ + return WT_Object::Font_Option_Width_Scale_ID; +} + +/////////////////////////////////////////////////////////////////////////// +WT_Object::WT_ID WT_Font_Option_Spacing::object_id() const +{ + return WT_Object::Font_Option_Spacing_ID; +} + +/////////////////////////////////////////////////////////////////////////// +WT_Object::WT_ID WT_Font_Option_Oblique::object_id() const +{ + return WT_Object::Font_Option_Oblique_ID; +} + +/////////////////////////////////////////////////////////////////////////// +WT_Object::WT_ID WT_Font_Option_Flags::object_id() const +{ + return WT_Object::Font_Option_Flags_ID; +} diff --git a/Whiptk702/logical_point.cpp b/Whiptk702/logical_point.cpp new file mode 100644 index 0000000..d66b569 --- /dev/null +++ b/Whiptk702/logical_point.cpp @@ -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 +#include + +/////////////////////////////////////////////////////////////////////////// +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 +#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 diff --git a/Whiptk702/transform.h b/Whiptk702/transform.h new file mode 100644 index 0000000..e1951fc --- /dev/null +++ b/Whiptk702/transform.h @@ -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