Attribute VB_Name = "VPSUBSVG" Rem **************************************************************************** Rem * vp_sub_scalable_vector_graphics.bas VIMAGE SOURCE MODULE * Rem * * Rem * VPSUBSVG.BAS -- VIMAGE: DER VIMAGE-SVG-INTERPRETER * Rem * ================================================== * Rem * * Rem * VPSUBSVG ist neben dem VPA-Assembler eine alternative Oberfläche, * Rem * die Plotlib ansteuern kann. * Rem * * Rem * SVG fetzt natürlich insofern mehr, das es ein weitverbreiteter Sprach- * Rem * standard ist. * Rem * * Rem * Der SVG-Interpreter realisiert eine nur eine kleine Untermenge von SVG. * Rem * * Rem * (C) ROLF BÖHM BAD SCHANDAU 2002, 2010, 2011 * Rem * * Rem * Dreidimensionale Register eingebaut. * Rem * * Rem * 11072006 RB Signaturenmittelpunkt immer mittig und nicht auf 1/3 Höhe * Rem * * Rem **************************************************************************** Option Explicit Rem Rem DER SVG-INTERPRETER Rem =================== Public Sub SVGInterpreter(LM1() As Single, n1 As Long, LM2() As Single, n2 As Long, Optional ProtocolMode As Long) Rem DER SVG-Interpreter plottet eine SVG-Datei in einem Bildspeicher LM1. Rem Hierzu bedient er sich zweier Teilprogramme, Rem - des Parsers SVGParser, der den Text analysiert, Rem - des Executors SVGExecute, der die Zeichnung ausführt. Rem Die Schnittstelle zwischen beiden Teilen ist die globale Struktur SVGElement Rem Das Interpretieren erfolgt grob in folgenden Schritten: Rem ... im SVG-Interpreter selbst: Rem PASS 1 -- ZEILEN ZÄHLEN Rem PASS 2 -- DATEI ZEILENWEISE EINLESEN Rem ... in SVG-Parser: Rem PASS 3 -- SYNTAKTISCHER PRÄPROZESSOR. ES WERDEN PROTOTOKEN **) GEBILDET Rem PASS 4 -- MEHRFACHLEERZEICHEN TILGEN Rem PASS 5 -- EINE RIESENGROSSE ZEILE DRAUS MACHEN Rem PASS 6 -- IN TOKEN TRENNEN. ES ENTSTEHT DIE ROHTOKENLISTE Rem PASS 7 -- LEERTOKEN UND KOMMENTARE TILGEN, PROTOTOKEN WIEDER ZURÜCKKODIEREN Rem PASS 8 -- TOKENTYPEN FESTELLEN. ES ENTSTEHT DIE TOKENLISTE Rem PASS 9 -- ELEMENTE EINSAMMELN. ELEMENTE UND ATTRIBUTE WERDEN ERMITTELT Rem UND NACH SVGElement EINGESAMMELT Rem ... in SVG-Executor: Rem PASS 10 -- ELEMENTE PLOTTEN Rem **) Zur Vermeidung kritischer Zeichenersetzungen werden Zeichen wie ", " «[EOC]» ") ' End of Comment TLine1 = Replace(TLine1, "/>", " «[EOX]» ") ' Top of Exit TLine1 = Replace(TLine1, "" Then TChar = " > " If TChar = "<" Then TChar = " < " If TChar = "=" Then TChar = " = " End If TLine2 = TLine2 & TChar Next j Rem Hinten noch einen Tokentrenner dran If IsInString = True Then TLine2 = TLine2 & Chr(SPACE_DUP_CODE) Else TLine2 = TLine2 & " " End If SVGLineArray(i) = TLine2 Next i Rem JETZT IST SVGLineArray PRÄPROZESSIERT, D. H. DIE TOKEN SIND VOR-GETRENNT, Rem KRITISCHE ZEICHEN SIND TEMPORÄR IN PROTOTOKEN UMKODIERT. Rem Rem PASS 4 -- MEHRFACHLEERZEICHEN TILGEN Rem ------------------------------------ For i = 1 To UBound(SVGLineArray) For k = 1 To 10 SVGLineArray(i) = Replace(SVGLineArray(i), " ", " ") Next k For k = 1 To 10 SVGLineArray(i) = Replace(SVGLineArray(i), " ", " ") Next k For k = 1 To 80 SVGLineArray(i) = Replace(SVGLineArray(i), Chr(SPACE_DUP_CODE) & Chr(SPACE_DUP_CODE), Chr(SPACE_DUP_CODE)) Next k Next i Rem JETZT GIBT ES IN SVGLineArray KEINE MEHRFACHLEERZEICHEN MEHR. Rem TOKEN WERDEN DURCH JE EIN LEERZEICHEN GETRENNT. Rem Rem PASS 5 -- EINE RIESENGROSSE ZEILE DRAUS MACHEN Rem ---------------------------------------------- TLine1 = "" For i = 1 To UBound(SVGLineArray) ' Über 65536 dürfen es nicht sein (Laufzeitfehler) If (Len(TLine2) + Len(SVGLineArray(i))) < 65525 Then TLine1 = TLine1 & SVGLineArray(i) End If Next i Rem JETZT STEHT ALLES IN DER RIESENGROSSEN ZEILE TLine1 Rem Rem PASS 6 -- IN TOKEN TRENNEN. ES ENTSTEHT DIE ROHTOKENLISTE Rem --------------------------------------------------------- SVGRawToken = Split(TLine1, " ") Rem JETZT STEHEN ALLE TOKEN IN DER ROHTOKENLISTE SVGRawToken TLine1 = "" Rem Rem PASS 7 -- LEERTOKEN UND KOMMENTARE TILGEN, PROTOTOKEN WIEDER ZURÜCKKODIEREN Rem --------------------------------------------------------------------------- ReDim SVGToken(1 To 1) ReDim SVGTokenType(1 To 1) ReDim SVGTokenElement(1 To 1) SVGTix = 0 For i = 0 To UBound(SVGRawToken) 'If SVGRawToken(i) <> "" And SVGRawToken(i) <> "=" Then ' Das Gleichheitszeichen ist redundant! If SVGRawToken(i) <> "" Then If SVGRawToken(i) = "«[TOC]»" Then CommentDeepth = CommentDeepth + 1 If CommentDeepth = 0 Then SVGTix = SVGTix + 1 ReDim Preserve SVGToken(1 To SVGTix) ReDim SVGTokenType(1 To SVGTix) ReDim SVGTokenElement(1 To SVGTix) SVGToken(SVGTix) = SVGRawToken(i) SVGToken(SVGTix) = Replace(SVGToken(SVGTix), "«[TOX]»", "") SVGToken(SVGTix) = Replace(SVGToken(SVGTix), "«[TOS]»", Chr(34)) SVGToken(SVGTix) = Replace(SVGToken(SVGTix), "«[EOS]»", Chr(34)) SVGToken(SVGTix) = Replace(SVGToken(SVGTix), Chr(SPACE_DUP_CODE), " ") End If If SVGRawToken(i) = "«[EOC]»" Then CommentDeepth = CommentDeepth - 1 End If Next i Rem JETZT IST DIE TOKENKLISTE SVGTokenList GEFÜLLT Rem Rem PASS 8 -- TOKENTYP FESTELLEN Rem ---------------------------- Rem Es gibt die Tokentypen nam (Bezeichner), val (Zahlenwert), dat (Zeichenkettendaten), Rem fix (feste Bedeutung) und any (unbekannte Bedeutung). For i = 1 To UBound(SVGToken) SVGTokenType(i) = "" ' Vorselektion TChar = Mid(SVGToken(i), 1, 1) Select Case TChar Case "A" To "Z", "a" To "z": SVGTokenType(i) = "nam" Case "0" To "9", "+", ".", "-": SVGTokenType(i) = "val" Case "<", ">", "/", "=": SVGTokenType(i) = "fix" Case Chr(34): If Mid(SVGToken(i), Len(SVGToken(i)), 1) = Chr(34) Then SVGTokenType(i) = "dat" Else SVGToken(i) = "any" End If Case Else: SVGTokenType(i) = "any" End Select ' Wenn Leerzeichen drin ist es kein Name If SVGTokenType(i) = "nam" And InStr(1, SVGToken(i), " ") <> 0 Then SVGTokenType(i) = "any" ' Wenn nicht in Zahl konvertierbar ist es keine Zahl If SVGTokenType(i) = "val" And IsNumeric(SVGToken(i)) = False Then SVGTokenType(i) = "any" Next i For i = 1 To UBound(SVGToken) If SVGTokenType(i) = "nam" Then SVGToken(i) = LCase(SVGToken(i)) If SVGTokenType(i) = "any" Then Call SVGPErr(i, "W201", "Token ist weder Festzeichen, noch Bezeichner, String oder Zahl") If SVGTokenType(i) = "val" Then Call SVGPErr(i, "W202", "Zahlentoken sollten in Doppelhochkomma stehen") Next i Rem JETZT IST FÜR JEDES TOKEN DER TOKENTYP BESTIMMT UND IN DER TOKENTYPLISTE Rem SVGTokenType EINEGTRAGEN Rem Rem PASS 9 -- ELEMENTE EINSAMMELN Rem ----------------------------- Rem Die Elemente werden in die SVG-Elementliste SVGElement eingesammelt. Rem Rem Es wird wie folgt anhand Status linear durchgeparst: Rem 0 Es wird ein < erwartet Rem 1 Es wird nach < ein Elementbezeichner erwartet Rem 2 Es wird nach dem Elementbezeichner ein Attributbezeichner erwartet Rem 3 Es wird nach dem Attributbezeichner ein = erwartet Rem 4 Es wird nach dem = ein Attributwert erwartet Status = 0 ' 0=nichts 1=element 2=attribut 3== 4=Attributdaten erwartet SVGEix = 0 ReDim SVGElement(0 To 0) For i = 1 To UBound(SVGToken) Select Case Status Case 0: ' Element wird erwartet. Oder auch ein " Then Status = 0: GoTo SVG9Exit If SVGTokenType(i) = "fix" And SVGToken(i) = "/>" Then SVGEix = SVGEix + 1 ReDim Preserve SVGElement(0 To SVGEix) SVGElement(SVGEix).name = "/" & SVGElement(SVGEix - 1).name SVGAix = 0 ReDim SVGElement(SVGEix).AttName(0 To 0) ReDim SVGElement(SVGEix).AttData(0 To 0) Status = 0 GoTo SVG9Exit End If If SVGTokenType(i) = "nam" Then SVGAix = SVGAix + 1 ReDim Preserve SVGElement(SVGEix).AttName(0 To SVGAix) ReDim Preserve SVGElement(SVGEix).AttData(0 To SVGAix) SVGElement(SVGEix).AttName(SVGAix) = SVGToken(i) SVGElement(SVGEix).AttData(SVGAix) = "" Status = 3 ' Jetzt wird ein Gleichheitszeichen erwartet Else Call SVGPErr(i, "W204", "Ein Attributbezeichner wurde vergeblich erwartet") End If Case 3: ' Gleichheitszeichen oder Elementende wird erwartert If SVGTokenType(i) = "fix" And SVGToken(i) = ">" Then Status = 0: GoTo SVG9Exit If SVGTokenType(i) = "fix" And SVGToken(i) = "/>" Then Status = 0: GoTo SVG9Exit If SVGTokenType(i) = "fix" And SVGToken(i) = "=" Then Status = 4 ' Jetzt werden Attributbezeichner erwartet Else Call SVGPErr(i, "I101", "Ein Attributbezeichner sollte von einem = gefolgt sein, geht aber auch so") Status = 4 ' Jetzt werden Attributbezeichner erwartet End If Case 4: ' Attributwert wird erwartet If SVGTokenType(i) = "fix" And SVGToken(i) = ">" Or SVGToken(i) = "/>" Then Call SVGPErr(i, "W206", "Unerwarteter Elementabschluss nach »=«, dem eigentlich ein Attributwert folgen soll") Status = 0 GoTo SVG9Exit End If Select Case SVGTokenType(i) Case "dat": s1 = Mid(SVGToken(i), 2, Len(SVGToken(i)) - 2) ' Doppelhochkommata wegmachen SVGElement(SVGEix).AttData(SVGAix) = s1 Status = 2 ' Jetzt wird der nächste Attributbezeichner erwartet Case "val": SVGElement(SVGEix).AttData(SVGAix) = SVGToken(i) Call SVGPErr(i, "I102", "Zahl auch ohne " & Chr(34) & " als Attributwert übernommen, was nicht völlig korrekt ist.") Status = 2 ' Jetzt wird der nächste Attributbezeichner erwartet Case Else Call SVGPErr(i, "W207", "Attributwert wurde vergeblich erwartet") End Select SVG9Exit: End Select Next i Rem JETZT IST DIE ELEMENTSTRUKTUR SVGElement MIT ALLEN ELEMENTEN UND ATTRIBUTEN GEFÜLLT .. Rem und tschüss ... End Sub Rem Rem DER SVG-EXEKUTOR Rem ================ Public Sub SVGExecute(LM1() As Single, n1 As Long, CreateImageFlag As Boolean, PlotFlag As Boolean) Rem Rem Der SVGExekutor entnimmt SVG-Elemente und -Attribute der Datenstruktur SVGElement, Rem stellt daraus Plotbefehle für die Plotlib zusammen und arbeitet alles ab. Rem Rem Der Code realisiert also die VIMAGE/SVG-Semantik. Rem Rem Es wird in Bildspeicher LM1, Nummer N1 geplottet. Rem Rem Es wird ein globales Fehlerprotokoll SVGMsgProt zurückgegeben. Rem Rem Auf Pixeladressen wird ein leicht zufälliges Epsilon addiert - aus folgendem Grund: Rem Rem Die Geokoordinaten stehen auf .5000 und werden mitunter (bei Linien, Rechtecken) mit 1.0000 Rem inkrementiert. Basic rundet auf die nächste gerade Zahl. So wird aud 1.5 2.5 3.5 4.5 --> Rem 2 2 4 4. Schöner Mist, er lässt dann jede 2. Zeile/Spalte aus. Mit dem Epsilon gehts aber. Rem Rem Anmerkung: Dies betrifft auch die Path-Data-Interpretation in der Plotlib. Dim Flag1 As Byte Dim Flag2 As Byte Dim Flag3 As Byte Dim Flag4 As Byte Dim Flag5 As Byte Dim Flag6 As Byte Dim Flag7 As Byte Dim Flag8 As Byte Dim Flag9 As Byte Dim i As Long Dim j As Long Dim k As Long Dim Width As Long ' Bildbreite Dim Height As Long ' Bildhöhe Dim x As Double ' Allg. x Dim y As Double ' Allg. y Dim r As Double ' Radien aller Art Dim R1 As Double Dim R2 As Double Dim s1 As String ' Allg. Zeichenketten aller Art Dim s2 As String Dim d1 As Double Dim Z1() As Single ' Farben Dim z2() As Single ' Farben Dim zd() As Single ' Dummyfarbe Dim P1(1 To 2) As Double ' Punkt 1 Dim P2(1 To 2) As Double ' Punkt 2 Dim pz(1 To 2) As Double ' Für Füllinitialpunkt Dim plist() As Double ' Für Polygon/Polyline-Punktliste Dim path As String ' Für Pfaddaten Dim ident As String ' Für Identstring Dim tmpPenSize As Long ' Rettungszelle Dim tmpValue() As Single ' Rettungszelle Dim workFillBorder() As Single ' Einstweiliger Grauwert für Rand bei Füllen If VIMAGETest = False Then On Error GoTo ErrLab GoTo ErrCon ErrLab: fixErrCode = 86: fixLastSystemErrCode = Err.Number: fixLastSystemErrDescription = Err.Description Exit Sub ErrCon: Rem Standardwerte in 4 Schichten Rem Rem INITIALISIERUNGEN Rem ----------------- ReDim Z1(1 To MAX_NUMBER_OF_CHANNELS) As Single ' Farben ReDim z2(1 To MAX_NUMBER_OF_CHANNELS) As Single ' Farben ReDim zd(1 To MAX_NUMBER_OF_CHANNELS) As Single ' Farben ReDim SVGDefValueStroke(1 To MAX_NUMBER_OF_CHANNELS) ReDim SVGDefValueFill(1 To MAX_NUMBER_OF_CHANNELS) ReDim SVGSvgValueStroke(1 To MAX_NUMBER_OF_CHANNELS) ReDim SVGSvgValueFill(1 To MAX_NUMBER_OF_CHANNELS) ReDim SVGGrpValueStroke(1 To MAX_NUMBER_OF_CHANNELS) ReDim SVGGrpValueFill(1 To MAX_NUMBER_OF_CHANNELS) ReDim SVGActValueStroke(1 To MAX_NUMBER_OF_CHANNELS) ReDim SVGActValueFill(1 To MAX_NUMBER_OF_CHANNELS) ReDim tmpValue(1 To MAX_NUMBER_OF_CHANNELS) ReDim workFillBorder(1 To MAX_NUMBER_OF_CHANNELS) If PLGIsInitialized = False Then Call SUBPltInit Call SUBPltSet("COORDMODE", 1) For i = 1 To MAX_NUMBER_OF_CHANNELS workFillBorder(i) = 19999 Next i workFillBorder(2) = -9999 ' sieht man so besser Rem Rem INITIALE STANDARDANNAHMEN Rem ------------------------- Call SVGCol2Value("black", "RGB", tmpValue) ' Strichfarbe schwarz Call VIMAGEValueCopy(tmpValue, SVGDefValueStroke) ' Keller 3 Call VIMAGEValueCopy(tmpValue, SVGSvgValueStroke) ' Keller 2 Call VIMAGEValueCopy(tmpValue, SVGGrpValueStroke) ' Keller 1 Call VIMAGEValueCopy(VIMAGEEmptyValue, SVGDefValueFill) ' Keller 3 ' Füllfarbe Leer Call VIMAGEValueCopy(VIMAGEEmptyValue, SVGSvgValueFill) ' Keller 2 Call VIMAGEValueCopy(VIMAGEEmptyValue, SVGGrpValueFill) ' Keller 1 SVGDefStrokeWidth = 10 ' Keller 3 ' Strichstärke 0.1 mm SVGSvgStrokeWidth = 10 ' Keller 2 SVGGrpStrokeWidth = 10 ' Keller 1 Call SUBPltSet("PENSIZE", 10) ' Erdgeschoss Rem Rem GROSSE INTERPRETATIONSSCHLEIFE Rem ------------------------------ For i = 1 To UBound(SVGElement) Select Case SVGElement(i).name Rem Rem DAS SVG-ELEMENT (LEGT BILDDEFINITION UND BASISSTANDARDS FEST) Rem ------------------------------------------------------------- Case "svg" ' INIT ident = "" Flag1 = 0: Flag2 = 0 ' STANDARDS SETZEN ' Call VIMAGEValueCopy(SVGDefValueStroke, SVGSvgValueStroke) ' Keller 2 ' Call VIMAGEValueCopy(SVGDefValueStroke, SVGGrpValueStroke) ' Keller 1 ' Call VIMAGEValueCopy(SVGDefValueStroke, SVGActValueStroke) ' Erdgeschoss ' Call VIMAGEValueCopy(SVGDefValueStroke, SVGSvgValueFill) ' Keller 2 ' Call VIMAGEValueCopy(SVGDefValueStroke, SVGGrpValueFill) ' Keller 1 ' Call VIMAGEValueCopy(SVGDefValueStroke, SVGActValueFill) ' Erdgeschoss ' SVGSvgStrokeWidth = SVGDefStrokeWidth ' Keller 2 ' SVGGrpStrokeWidth = SVGDefStrokeWidth ' Keller 1 Call SUBPltSet("PENSIZE", SVGDefStrokeWidth) ' Erdgeschoss ' INTERPRETATION For j = 1 To UBound(SVGElement(i).AttName) Select Case SVGElement(i).AttName(j) Case "width": Width = VIMAGEVal(SVGElement(i).AttData(j)) If Width > 2 Then Flag1 = 1 Case "height": Height = VIMAGEVal(SVGElement(i).AttData(j)) If Height > 2 Then Flag2 = 1 Case "fill" Call SVGExecFill(SVGElement(i).AttData(j)) Call VIMAGEValueCopy(SVGActValueFill, SVGSvgValueFill) Case "stroke" Call SVGExecStroke(SVGElement(i).AttData(j)) SVGSvgStrokeWidth = PLTPenSize Call VIMAGEValueCopy(SVGActValueStroke, SVGSvgValueStroke) Case "stroke-width" Call SVGExecStroke_Width(SVGElement(i).AttData(j)) SVGSvgStrokeWidth = PLTPenSize Case "style" Call SVGExecStyle(SVGElement(i).AttData(j)) If fixErrCode <> 0 Then Call SVGPErr(0 - i, "W445", "Unbekanntes Argument im Style-Attribut") Call VIMAGEValueCopy(SVGActValueFill, SVGSvgValueFill) SVGSvgStrokeWidth = PLTPenSize Call VIMAGEValueCopy(SVGActValueStroke, SVGSvgValueStroke) Case "id" ident = LCase(SVGElement(i).AttData(j)) End Select Next j ' EXEKUTION If Flag1 * Flag2 = 1 Then If CreateImageFlag = True Then RMIsInUse(n1) = True If ident <> "" Then RMFn(n1) = SVGGroupPrefix & ident & ".fix" Else RMFn(n1) = "" Call FIXHdrInit(RMHD(n1), Width + 1, Height + 1, 3, 1, "BYTE") RMHD(n1).GeoSWPX = 0 - Width * 0.5 RMHD(n1).GeoNEPX = 0 + Width * 0.5 RMHD(n1).GeoSWPY = 0 - Height * 0.5 RMHD(n1).GeoNEPY = 0 + Height * 0.5 RMHD(n1).GeoNUni = "F" ' 1/100 mm RMHD(n1).RadMode = "RGB" RMHD(n1).RadBLev = 255 RMHD(n1).RadWLev = 0 Call FIXMatClear(RMHD(0), LM1, VIMAGENullValue, HF.Text2, HF.ProgressBar1) End If End If SVGSignaturName = ident ' ermittelte SVG-Standards werden Gruppenstandards Call VIMAGEValueCopy(SVGSvgValueFill, SVGGrpValueFill) Call VIMAGEValueCopy(SVGSvgValueStroke, SVGGrpValueStroke) SVGGrpStrokeWidth = SVGSvgStrokeWidth Rem Rem DAS G-ELEMENT (LEGT STANDARDS FEST) Rem ----------------------------------- Case "g" ' INIT ' ... keine ... ' STANDARDS SETZEN ' Call VIMAGEValueCopy(SVGSvgValueStroke, SVGGrpValueStroke) ' Keller 1 ' Call VIMAGEValueCopy(SVGSvgValueFill, SVGGrpValueFill) ' Keller 1 ' SVGGrpStrokeWidth = SVGSvgStrokeWidth ' Keller 1 ' INTERPRETATION For j = 1 To UBound(SVGElement(i).AttName) ' Attribute abklappern Select Case SVGElement(i).AttName(j) Case "id" ident = LCase(SVGElement(i).AttData(j)) Case "fill" Call SVGExecFill(SVGElement(i).AttData(j)) Call VIMAGEValueCopy(SVGActValueFill, SVGGrpValueFill) Case "stroke" Call SVGExecStroke(SVGElement(i).AttData(j)) SVGGrpStrokeWidth = PLTPenSize Call VIMAGEValueCopy(SVGActValueStroke, SVGGrpValueStroke) Case "stroke-width" Call SVGExecStroke_Width(SVGElement(i).AttData(j)) SVGGrpStrokeWidth = PLTPenSize Case "style" Call SVGExecStyle(SVGElement(i).AttData(j)) If fixErrCode <> 0 Then Call SVGPErr(0 - i, "W445", "Unbekanntes Argument im Style-Attribut") Call VIMAGEValueCopy(SVGActValueFill, SVGGrpValueFill) SVGGrpStrokeWidth = PLTPenSize Call VIMAGEValueCopy(SVGActValueStroke, SVGGrpValueStroke) End Select Next j ' EXEKUTION If ident <> "" Then RMFn(n1) = SVGGroupPrefix & ident & ".fix" Else RMFn(n1) = "" SVGSignaturName = ident Rem Rem DAS LINE-ELEMENT Rem ---------------- Case "line" If PlotFlag = True Then ' INIT Flag1 = 0: Flag2 = 0: Flag3 = 0: Flag4 = 0 ' STANDARDS SETZEN Call VIMAGEValueCopy(SVGGrpValueStroke, SVGActValueStroke) ' Erdgeschoss Call VIMAGEValueCopy(SVGGrpValueFill, SVGActValueFill) ' Erdgeschoss Call SUBPltSet("PENSIZE", SVGGrpStrokeWidth) ' Erdgeschoss ' INTERPRETATION For j = 1 To UBound(SVGElement(i).AttName) ' Attribute abklappern Select Case SVGElement(i).AttName(j) Case "x1": P1(1) = VIMAGEVal(SVGElement(i).AttData(j)) + VIMAGERandomEpsilon(13) Flag1 = 1 Case "y1": P1(2) = VIMAGEVal(SVGElement(i).AttData(j)) + VIMAGERandomEpsilon(14) Flag2 = 1 Case "x2": P2(1) = VIMAGEVal(SVGElement(i).AttData(j)) + VIMAGERandomEpsilon(15) Flag3 = 1 Case "y2": P2(2) = VIMAGEVal(SVGElement(i).AttData(j)) + VIMAGERandomEpsilon(16) Flag4 = 1 Case "fill" Call SVGExecFill(SVGElement(i).AttData(j)) Case "stroke" Call SVGExecStroke(SVGElement(i).AttData(j)) Case "stroke-width" Call SVGExecStroke_Width(SVGElement(i).AttData(j)) Case "style" Call SVGExecStyle(SVGElement(i).AttData(j)) If fixErrCode <> 0 Then Call SVGPErr(0 - i, "W445", "Unbekanntes Argument im Style-Attribut") End Select Next j ' EXEKUTION If Flag1 * Flag2 * Flag3 * Flag4 = 1 Then Call SUBPltLine(LM1, n1, P1, P2, SVGActValueStroke) SVGMsgProt = SVGMsgProt & "P001/LINE/Stroke : " & SVGPVec(SVGActValueStroke) & vbCrLf Else Call SVGPErr(0 - i, "W401", "-Element nicht gezeichnet, weil x1, y1, x2 oder y2 fehlte(n)") End If End If Rem Rem DAS RECT-ELEMENT Rem ---------------- Case "rect" If PlotFlag = True Then ' INIT Flag1 = 0: Flag2 = 0: Flag3 = 0: Flag4 = 0 ' STANDARDS SETZEN Call VIMAGEValueCopy(SVGGrpValueStroke, SVGActValueStroke) ' Erdgeschoss Call VIMAGEValueCopy(SVGGrpValueFill, SVGActValueFill) ' Erdgeschoss Call SUBPltSet("PENSIZE", SVGGrpStrokeWidth) ' Erdgeschoss ' INTERPRETATION For j = 1 To UBound(SVGElement(i).AttName) ' Attribute abklappern Select Case SVGElement(i).AttName(j) Case "x": P1(1) = VIMAGEVal(SVGElement(i).AttData(j)) + VIMAGERandomEpsilon(17) Flag1 = 1 Case "y": P1(2) = VIMAGEVal(SVGElement(i).AttData(j)) + VIMAGERandomEpsilon(18) Flag2 = 1 Case "height": P2(2) = P1(2) + VIMAGEVal(SVGElement(i).AttData(j)) + VIMAGERandomEpsilon(19) Flag3 = 1 Flag3 = 1 Case "width": P2(1) = P1(1) + VIMAGEVal(SVGElement(i).AttData(j)) + VIMAGERandomEpsilon(20) Flag4 = 1 Case "fill" Call SVGExecFill(SVGElement(i).AttData(j)) Case "stroke" Call SVGExecStroke(SVGElement(i).AttData(j)) Case "stroke-width" Call SVGExecStroke_Width(SVGElement(i).AttData(j)) Case "style" Call SVGExecStyle(SVGElement(i).AttData(j)) If fixErrCode <> 0 Then Call SVGPErr(0 - i, "W445", "Unbekanntes Argument im Style-Attribut") End Select Next j ' EXEKUTION If Flag1 * Flag2 * Flag3 * Flag4 = 1 Then Call SUBPltRect(LM1, n1, P1, P2, SVGActValueStroke, SVGActValueFill) SVGMsgProt = SVGMsgProt & "P002/RECT/Str/F : " & SVGPVec(SVGActValueStroke) & " / " & SVGPVec(SVGActValueFill) & vbCrLf Else Call SVGPErr(0 - i, "W402", "-Element nicht gezeichnet, weil x, y, width oder height fehlte(n)") End If End If Rem Rem DAS CIRCLE-ELEMENT Rem ------------------ Case "circle" If PlotFlag = True Then ' INIT Flag1 = 0: Flag2 = 0: Flag3 = 0 ' STANDARDS SETZEN Call VIMAGEValueCopy(SVGGrpValueStroke, SVGActValueStroke) ' Erdgeschoss Call VIMAGEValueCopy(SVGGrpValueFill, SVGActValueFill) ' Erdgeschoss Call SUBPltSet("PENSIZE", SVGGrpStrokeWidth) ' Erdgeschoss ' INTERPRETATION For j = 1 To UBound(SVGElement(i).AttName) ' Attribute abklappern Select Case SVGElement(i).AttName(j) Case "cx": P1(1) = VIMAGEVal(SVGElement(i).AttData(j)) Flag1 = 1 Case "cy": P1(2) = VIMAGEVal(SVGElement(i).AttData(j)) Flag2 = 1 Case "r": R1 = VIMAGEVal(SVGElement(i).AttData(j)) Flag3 = 1 Case "fill" Call SVGExecFill(SVGElement(i).AttData(j)) Case "stroke" Call SVGExecStroke(SVGElement(i).AttData(j)) Case "stroke-width" Call SVGExecStroke_Width(SVGElement(i).AttData(j)) Case "style" Call SVGExecStyle(SVGElement(i).AttData(j)) If fixErrCode <> 0 Then Call SVGPErr(0 - i, "W445", "Unbekanntes Argument im Style-Attribut") End Select Next j ' EXEKUTION If Flag1 * Flag2 * Flag3 = 1 Then Call SUBPltCircle(LM1, n1, P1, R1, SVGActValueStroke, SVGActValueFill) SVGMsgProt = SVGMsgProt & "P003/CIRCLE/Str/F: " & SVGPVec(SVGActValueStroke) & " / " & SVGPVec(SVGActValueFill) & vbCrLf Else Call SVGPErr(0 - i, "W403", "-Element nicht gezeichnet, weil ein cx, cy oder r fehlte(n)") End If End If Rem Rem DAS ELLIPSE-ELEMENT Rem ------------------- Case "ellipse" If PlotFlag = True Then ' INIT Flag1 = 0: Flag2 = 0: Flag3 = 0: Flag3 = 0 ' STANDARDS SETZEN Call VIMAGEValueCopy(SVGGrpValueStroke, SVGActValueStroke) ' Erdgeschoss Call VIMAGEValueCopy(SVGGrpValueFill, SVGActValueFill) ' Erdgeschoss Call SUBPltSet("PENSIZE", SVGGrpStrokeWidth) ' Erdgeschoss ' INTERPRETATION For j = 1 To UBound(SVGElement(i).AttName) ' Attribute abklappern Select Case SVGElement(i).AttName(j) Case "cx": P1(1) = VIMAGEVal(SVGElement(i).AttData(j)) Flag1 = 1 Case "cy": P1(2) = VIMAGEVal(SVGElement(i).AttData(j)) Flag2 = 1 Case "rx": R1 = VIMAGEVal(SVGElement(i).AttData(j)) Flag3 = 1 Case "ry": R2 = VIMAGEVal(SVGElement(i).AttData(j)) Flag4 = 1 Case "fill" Call SVGExecFill(SVGElement(i).AttData(j)) Case "stroke" Call SVGExecStroke(SVGElement(i).AttData(j)) Case "stroke-width" Call SVGExecStroke_Width(SVGElement(i).AttData(j)) Case "style" Call SVGExecStyle(SVGElement(i).AttData(j)) If fixErrCode <> 0 Then Call SVGPErr(0 - i, "W445", "Unbekanntes Argument im Style-Attribut") End Select Next j ' EXEKUTION If Flag1 * Flag2 * Flag3 * Flag4 = 1 Then Call SUBPltEllipse(LM1, n1, P1, R1, R2, SVGActValueStroke, SVGActValueFill) SVGMsgProt = SVGMsgProt & "P004/ELLIPS/Str/F: " & SVGPVec(SVGActValueStroke) & " / " & SVGPVec(SVGActValueFill) & vbCrLf Else Call SVGPErr(0 - i, "W404", "-Element nicht gezeichnet, weil cx, cy, rx oder ry fehlte(n)") End If End If Rem Rem DAS POLYLINE-ELEMENT Rem -------------------- Case "polyline" If PlotFlag = True Then ' INIT Flag1 = 0 ' STANDARDS SETZEN Call VIMAGEValueCopy(SVGGrpValueStroke, SVGActValueStroke) ' Erdgeschoss Call VIMAGEValueCopy(SVGGrpValueFill, SVGActValueFill) ' Erdgeschoss Call SUBPltSet("PENSIZE", SVGGrpStrokeWidth) ' Erdgeschoss ' INTERPRETATION For j = 1 To UBound(SVGElement(i).AttName) ' Attribute abklappern Select Case SVGElement(i).AttName(j) Case "points": s1 = SVGElement(i).AttData(j) For k = 1 To 10 ' das macht bis zu 1024 Leerzeichen zu einem Leerzeichen s1 = Replace(s1, " ", " ") Next k s1 = RTrim(LTrim(s1)) ' Führende Space weg, die würden jetzt gleich Kommata s1 = Replace(s1, " ", ",") Call VIMAGEParseDoubleArrayToken(s1, plist) Flag1 = 1 Case "fill" Call SVGExecFill(SVGElement(i).AttData(j)) Case "stroke" Call SVGExecStroke(SVGElement(i).AttData(j)) Case "stroke-width" Call SVGExecStroke_Width(SVGElement(i).AttData(j)) Case "style" Call SVGExecStyle(SVGElement(i).AttData(j)) If fixErrCode <> 0 Then Call SVGPErr(0 - i, "W445", "Unbekanntes Argument im Style-Attribut") End Select Next j For k = 1 To UBound(plist) plist(k) = plist(k) + VIMAGERandomEpsilon(k Mod 32) Next k ' EXEKUTION If Flag1 = 1 Then Call SUBPltPolyline(LM1, n1, plist, SVGActValueStroke) SVGMsgProt = SVGMsgProt & "P005/PLIN/Stroke : " & (UBound(plist) / 2) & " Points, " & SVGPVec(SVGActValueStroke) & vbCrLf Else Call SVGPErr(0 - i, "W405", "-Element nicht gezeichnet, weil points fehlte") End If End If Rem Rem DAS POLYGON-ELEMENT Rem ------------------- Case "polygon" If PlotFlag = True Then ' INIT Flag1 = 0: Flag8 = 0: Flag9 = 0 ' STANDARDS SETZEN Call VIMAGEValueCopy(SVGGrpValueStroke, SVGActValueStroke) ' Erdgeschoss Call VIMAGEValueCopy(SVGGrpValueFill, SVGActValueFill) ' Erdgeschoss Call SUBPltSet("PENSIZE", SVGGrpStrokeWidth) ' Erdgeschoss ' INTERPRETATION For j = 1 To UBound(SVGElement(i).AttName) ' Attribute abklappern Select Case SVGElement(i).AttName(j) Case "points": s1 = SVGElement(i).AttData(j) For k = 1 To 10 ' das macht bis zu 1024 Leerzeichen zu einem Leerzeichen s1 = Replace(s1, " ", " ") Next k s1 = LTrim(RTrim(s1)) s1 = Replace(s1, " ", ",") Call VIMAGEParseDoubleArrayToken(s1, plist) Flag1 = 1 Case "zx" pz(1) = VIMAGEVal(SVGElement(i).AttData(j)) Flag8 = 1 Case "zy" pz(2) = VIMAGEVal(SVGElement(i).AttData(j)) Flag9 = 1 Case "fill" Call SVGExecFill(SVGElement(i).AttData(j)) Case "stroke" Call SVGExecStroke(SVGElement(i).AttData(j)) Case "stroke-width" Call SVGExecStroke_Width(SVGElement(i).AttData(j)) Case "style" Call SVGExecStyle(SVGElement(i).AttData(j)) If fixErrCode <> 0 Then Call SVGPErr(0 - i, "W445", "Unbekanntes Argument im Style-Attribut") End Select Next j For k = 1 To UBound(plist) plist(k) = plist(k) + VIMAGERandomEpsilon(k Mod 32) Next k ' EXEKUTION ' Polygonfläche füllen If SVGActValueFill(1) <> -9999 Then If Flag1 * Flag8 * Flag9 = 1 Then tmpPenSize = PLTPenSize ' retten Call SUBPltSet("PENSIZE", 1) ' 1 breit umgrenzen Call SUBPltPolygon(LM1, n1, plist, workFillBorder) ' Umgrenzung malen SVGMsgProt = SVGMsgProt & "P006/PGON/Contour: " & (UBound(plist) / 2) & " Points " & vbCrLf Call SUBPltSet("PENSIZE", tmpPenSize) ' Alte Stiftbreite wiederherstellen fixErrCode = 0 Call SUBPltFill(LM1, n1, pz, workFillBorder, SVGActValueFill) ' und alles bis workFillBorder füllen SVGMsgProt = SVGMsgProt & "P007/PGON/Fill : " & SVGPVec(SVGActValueStroke) & vbCrLf If fixErrCode <> 0 Then Call SVGPErr(0 - i, "W442", "Fehler beim Füllen eines -Elementes. Fehlercode " & fixErrCode) End If End If ' Polygonumriss plotten If Flag1 = 1 Then Call SUBPltPolygon(LM1, n1, plist, SVGActValueStroke) SVGMsgProt = SVGMsgProt & "P008/PGON/Stroke : " & (UBound(plist) / 2) & " Points, " & SVGPVec(SVGActValueStroke) & vbCrLf Else Call SVGPErr(0 - i, "W406", "-Element gezeichnet, weil points fehlte") End If ' Fehlermeldung, wenn kein Füllen angewiesen und kein Füllanfangspunkt If SVGActValueFill(1) <> -9999 And Flag8 * Flag9 <> 1 Then Call SVGPErr(0 - i, "W447", "-Element konnte nicht gefüllt werden, weil zx oder zy fehlte.") End If End If Rem Rem DAS PATH-ELEMENT Rem ---------------- Case "path" If PlotFlag = True Then ' INIT Flag1 = 0: Flag2 = 0: Flag3 = 0: Flag3 = 0 Flag8 = 0: Flag9 = 0 ' STANDARDS SETZEN Call VIMAGEValueCopy(SVGGrpValueStroke, SVGActValueStroke) ' Erdgeschoss Call VIMAGEValueCopy(SVGGrpValueFill, SVGActValueFill) ' Erdgeschoss Call SUBPltSet("PENSIZE", SVGGrpStrokeWidth) ' Erdgeschoss ' INTERPRETATION For j = 1 To UBound(SVGElement(i).AttName) ' Attribute abklappern Select Case SVGElement(i).AttName(j) Case "d": path = SVGElement(i).AttData(j) Flag1 = 1 Case "zx" pz(1) = VIMAGEVal(SVGElement(i).AttData(j)) Flag8 = 1 Case "zy" pz(2) = VIMAGEVal(SVGElement(i).AttData(j)) Flag9 = 1 Case "fill" Call SVGExecFill(SVGElement(i).AttData(j)) Case "stroke" Call SVGExecStroke(SVGElement(i).AttData(j)) Case "stroke-width" Call SVGExecStroke_Width(SVGElement(i).AttData(j)) Case "style" Call SVGExecStyle(SVGElement(i).AttData(j)) If fixErrCode <> 0 Then Call SVGPErr(0 - i, "W445", "Unbekanntes Argument im Style-Attribut") End Select Next j ' EXECUTION ' Pfadfläche füllen If SVGActValueFill(1) <> -9999 Then If Flag1 * Flag8 * Flag9 = 1 Then tmpPenSize = PLTPenSize ' Stiftbreite retten Call SUBPltSet("PENSIZE", 1) ' und auf 1 setzen Call SUBPltPath(LM1, n1, path, workFillBorder) ' Umgrenzung malen SVGMsgProt = SVGMsgProt & "P009/PATH/Contour:" & path & vbCrLf Call SUBPltSet("PENSIZE", tmpPenSize) ' Alte Stiftbreite wiederherstellen fixErrCode = 0 Call SUBPltFill(LM1, n1, pz, workFillBorder, SVGActValueFill) ' und alles bis workFillBorder füllen SVGMsgProt = SVGMsgProt & "P010/PATH/Fill : " & SVGPVec(SVGActValueStroke) & vbCrLf If fixErrCode <> 0 Then Call SVGPErr(0 - i, "W442", "Fehler beim Füllen eines -Elementes. Fehlercode " & fixErrCode) End If End If ' Pfadumriss plotten If Flag1 = 1 Then fixErrCode = 0 Call SUBPltPath(LM1, n1, path, SVGActValueStroke) SVGMsgProt = SVGMsgProt & "P011/PATH/Data :" & path & vbCrLf ' Künftig die "W444" nicht ändern: Die wird im UP ausgewertet! If fixErrCode <> 0 Then Call SVGPErr(0 - i, "W444", "Fehler beim Zeichnen eines -Elementes. Fehlercode " & fixErrCode) Else Call SVGPErr(0 - i, "W406", "-Element nicht gezeichnet, weil das Datenattribut d fehlte") End If ' Fehlermeldung wenn kein Füllanfangspunkt If SVGActValueFill(1) <> -9999 And Flag8 * Flag9 <> 1 Then Call SVGPErr(0 - i, "W447", "-Element konnte nicht gefüllt werden, weil zx oder zy fehlte.") End If End If ' Case "/line", "/rect", "/circle", "/ellipse", "/polygon", "/polyline", "/path": ' unnötig, die werden immer am Anfang gestetzt. ' Call VIMAGEValueCopy(SVGGrpValueStroke, SVGActValueStroke) ' Erdgeschoss ' Call VIMAGEValueCopy(SVGGrpValueFill, SVGActValueFill) ' Erdgeschoss ' Call SUBPltSet("PENSIZE", SVGGrpStrokeWidth) ' Erdgeschoss Rem Rem ELEMENTE-SCHLIESSUNGEN Rem ---------------------- Case "/g": ' STANDARDS ZURÜCKSETZEN ' Ganz sauber ist das nicht, eigentlich müsste es einen g-Stack geben, ' aber wir wollen es mal nicht übertreiben ... Call VIMAGEValueCopy(SVGSvgValueStroke, SVGGrpValueStroke) ' Keller 1 Call VIMAGEValueCopy(SVGSvgValueFill, SVGGrpValueFill) ' Keller 1 SVGGrpStrokeWidth = SVGSvgStrokeWidth ' Keller 1 Case "/svg": ' STANDARDS ZURÜCKSETZEN ' Eigentlich überflüssig, denn, bei /svg ist Schluss ... Call VIMAGEValueCopy(SVGDefValueStroke, SVGSvgValueStroke) ' Keller 2 Call VIMAGEValueCopy(SVGDefValueStroke, SVGGrpValueStroke) ' Keller 1 Call VIMAGEValueCopy(SVGDefValueStroke, SVGActValueStroke) ' Erdgeschoss Call VIMAGEValueCopy(SVGDefValueStroke, SVGSvgValueFill) ' Keller 2 Call VIMAGEValueCopy(SVGDefValueStroke, SVGGrpValueFill) ' Keller 1 Call VIMAGEValueCopy(SVGDefValueStroke, SVGActValueFill) ' Erdgeschoss SVGSvgStrokeWidth = SVGDefStrokeWidth ' Keller 2 SVGGrpStrokeWidth = SVGDefStrokeWidth ' Keller 1 End Select Next i Rem ENDE GROSSE INTERPRETATIONSSCHLEIFE End Sub Rem Rem ATTRIBUT-UNTERPROGRAMME DES EXEKUTORS Rem ------------------------------------- Rem FILL-ATTRIBUT EXEKUTIEREN Public Sub SVGExecFill(Attributwert As String) Rem Rem SVGExecFill exekutiert ein fill-Attribut. Rem Dim s As String Dim z() As Single s = LCase(Attributwert) Call SVGCol2Value(Attributwert, "RGB", z) If s = "none" Then Call VIMAGEValueCopy(VIMAGEEmptyValue, SVGActValueFill) Else Call VIMAGEValueCopy(z, SVGActValueFill) End If End Sub Rem STROKE-ATTRIBUT EXEKUTIEREN Public Sub SVGExecStroke(Attributwert As String) Rem Rem SVGExecStroke exekutiert ein stroke-Attribut. Rem Dim s As String Dim z() As Single s = LCase(Attributwert) Call SVGCol2Value(Attributwert, "RGB", z) If s = "none" Then Call VIMAGEValueCopy(VIMAGEEmptyValue, SVGActValueStroke) Call SUBPltSet("PENSIZE", 0) Else Call VIMAGEValueCopy(z, SVGActValueStroke) If PLTPenSize = 0 Then Call SUBPltSet("PENSIZE", SVGGrpStrokeWidth) ' Falls 0 dann Strichstärke aus dem Gruppenstandard holen If PLTPenSize = 0 Then Call SUBPltSet("PENSIZE", SVGSvgStrokeWidth) ' Falls 0 dann Strichstärke aus dem Gruppenstandard holen If PLTPenSize = 0 Then Call SUBPltSet("PENSIZE", SVGDefStrokeWidth) ' Falls 0 dann Strichstärke aus dem Gruppenstandard holen End If End Sub Rem STROKE-WIDTH-ATTRIBUT EXEKUTIEREN Public Sub SVGExecStroke_Width(Attributwert As String) Rem Rem SVGExecStroke_Width exekutiert ein stroke-width-Attribut. Rem Dim d1 As Double d1 = VIMAGEVal(Attributwert) Call SUBPltSet("PENSIZE", d1) End Sub Rem STYLE-ATTRIBUT EXEKUTIEREN Public Sub SVGExecStyle(Attributwert As String) Rem Rem SVGExecStroke_Width exekutiert ein style-Attribut. Rem Dim i As Long Dim s As String Dim a() As String ' Tokenarray fixErrCode = 0 s = LCase(Attributwert) s = Replace(s, ":", ": ") s = Replace(s, ";", " ") s = Replace(s, ",", " ") s = LTrim(RTrim(s)) a = Split(s, " ") For i = 0 To UBound(a) - 1 Step 2 Select Case a(i) Case "stroke-width:" Call SVGExecStroke_Width(a(i + 1)) Case "stroke:" Call SVGExecStroke(a(i + 1)) Case "fill:" Call SVGExecFill(a(i + 1)) Case Else fixErrCode = 87 ' Das akkumuliert auch End Select Next i End Sub Rem Rem FARBE BEREITSTELLEN Rem ------------------- Public Sub SVGCol2Value(Colorname As String, Farbmodell As String, Value() As Single) Rem Rem SVGCol2Vector wandelt einen HTML-Farbnamen in einem Grauwertvektor um. Rem Dim i As Long Dim T As String Dim t1 As String Dim t2 As String Dim v() As String ReDim Value(1 To MAX_NUMBER_OF_CHANNELS) For i = 1 To MAX_NUMBER_OF_CHANNELS Value(i) = 0 Next i T = LCase(Colorname) Rem NETSCAPE-FARBNAME t1 = T If t1 = "lavenderblush" Then t1 = "lav.blus" If t1 = "lightgreen" Then t1 = "lig.gree" If t1 = "lightgrey" Then t1 = "lig.grey" If t1 = "darkslateblue" Then t1 = "d.slateb" If t1 = "darkslategrey" Then t1 = "d.slateg" t1 = Left(t1 + "~~~~~~~~", 8) t2 = "" Select Case t1 ' 16 VGA-Farben Case "black~~~": t2 = "#000000" Case "maroon~~": t2 = "#800000" Case "green~~~": t2 = "#008000" Case "olive~~~": t2 = "#808000" Case "navy~~~~": t2 = "#000080" Case "purple~~": t2 = "#800080" Case "teal~~~~": t2 = "#008080" Case "silver~~": t2 = "#c0c0c0" Case "gray~~~~": t2 = "#808080" Case "red~~~~~": t2 = "#ff0000" Case "lime~~~~": t2 = "#00ff00" Case "yellow~~": t2 = "#ffff00" Case "blue~~~~": t2 = "#0000ff" Case "fuchsia~": t2 = "#ff00ff" Case "aqua~~~~": t2 = "#00ffff" Case "white~~~": t2 = "#ffffff" ' Zusätzlich cyan und magenta: Case "cyan~~~~": t2 = "#00ffff" Case "magenta~": t2 = "#ff00ff" ' 120 Netscape-Farben Case "aliceblu": t2 = "#f0f8ff" Case "antiquew": t2 = "#faebd7" Case "aquamari": t2 = "#7fffd4" Case "azure~~~": t2 = "#f0ffff" Case "beige~~~": t2 = "#f5f5dc" Case "blueviol": t2 = "#8a2be2" Case "brown~~~": t2 = "#a52a2a" Case "burlywoo": t2 = "#deb887" Case "cadetblu": t2 = "#5f9ea0" Case "chartreu": t2 = "#7fff00" Case "chocolat": t2 = "#d2691e" Case "coral~~~": t2 = "#ff7f50" Case "cornflow": t2 = "#6495ed" Case "cornsilk": t2 = "#fff8dc" Case "crimson~": t2 = "#dc143c" Case "darkblue": t2 = "#00008b" Case "darkcyan": t2 = "#008b8b" Case "darkgold": t2 = "#b8860b" Case "darkgrey": t2 = "#a9a9a9" Case "darkgree": t2 = "#006400" Case "darkkhak": t2 = "#bdb76b" Case "darkmage": t2 = "#8b008b" Case "darkoliv": t2 = "#556b2f" Case "darkoran": t2 = "#ff8c00" Case "darkorch": t2 = "#9932cc" Case "darkred~": t2 = "#8b0000" Case "darksalo": t2 = "#e9967a" Case "darkseag": t2 = "#8fbc8f" Case "d.slateb": t2 = "#483d8b" ' darkslateblue Case "d.slateg": t2 = "#2f4f4f" ' darkslategrey Case "darkturq": t2 = "#00ced1" Case "darkviol": t2 = "#9400d3" Case "deeppink": t2 = "#ff1493" Case "deepskyb": t2 = "#00bfff" Case "dimgray~": t2 = "#696969" Case "dodgerbl": t2 = "#1e90ff" Case "firebric": t2 = "#b22222" Case "floralwh": t2 = "#fffaf0" Case "forestgr": t2 = "#228b22" Case "gainsbor": t2 = "#dcdcdc" Case "ghostwhi": t2 = "#f8f8ff" Case "gold~~~~": t2 = "#ffd700" Case "goldenro": t2 = "#daa520" Case "greenyel": t2 = "#adff2f" Case "honeydew": t2 = "#f0fff0" Case "hotpink~": t2 = "#ff69b4" Case "indianre": t2 = "#cd5c5c" Case "indigo~~": t2 = "#4b0082" Case "ivory~~~": t2 = "#fffff0" Case "khaki~~~": t2 = "#f0e68c" Case "lavender": t2 = "#e6e6fa" Case "lav.blus": t2 = "#fff0f5" ' lavenderblush Case "lemonchi": t2 = "#fffacd" Case "lightblu": t2 = "#add8e6" Case "lightcor": t2 = "#f08080" Case "lightcya": t2 = "#e0ffff" Case "lightgol": t2 = "#fafad2" Case "lig.gree": t2 = "#90ee90" ' lightgreen Case "lig.grey": t2 = "#d3d3d3" ' lightgrey Case "lightpin": t2 = "#ffb6c1" Case "lightsal": t2 = "#ffa07a" Case "lightsea": t2 = "#20b2aa" Case "lightsky": t2 = "#87cefa" Case "lightsla": t2 = "#778899" Case "lightste": t2 = "#b0c4de" Case "lightyel": t2 = "#ffffe0" Case "limegree": t2 = "#32cd32" Case "linen~~~": t2 = "#faf0e6" Case "mediumaq": t2 = "#66cdaa" Case "mediumbl": t2 = "#0000cd" Case "mediumor": t2 = "#ba55d3" Case "mediumpu": t2 = "#9370db" Case "mediumse": t2 = "#3cb371" Case "mediumsl": t2 = "#7b68ee" Case "mediumsp": t2 = "#00fa9a" Case "mediumtu": t2 = "#48d1cc" Case "mediumvi": t2 = "#c71585" Case "midnight": t2 = "#191970" Case "mintcrea": t2 = "#f5fffa" Case "mistyros": t2 = "#ffe4e1" Case "moccasin": t2 = "#ffe4b5" Case "navajowh": t2 = "#ffdead" Case "oldlace~": t2 = "#fdf5e6" Case "olivedra": t2 = "#6b8e23" Case "orange~~": t2 = "#ffa500" Case "orangere": t2 = "#ff4500" Case "orchid~~": t2 = "#da70d6" Case "palegold": t2 = "#eee8aa" Case "palegree": t2 = "#98fb98" Case "paleturq": t2 = "#afeeee" Case "paleviol": t2 = "#db7093" Case "papayawh": t2 = "#ffefd5" Case "peachpuf": t2 = "#ffdab9" Case "peru~~~~": t2 = "#cd853f" Case "pink~~~~": t2 = "#ffc0cb" Case "plum~~~~": t2 = "#dda0dd" Case "powderbl": t2 = "#b0e0e6" Case "rosybrow": t2 = "#bc8f8f" Case "royalblu": t2 = "#4169e1" Case "saddlebr": t2 = "#8b4513" Case "salmon~~": t2 = "#fa8072" Case "sandybro": t2 = "#f4a460" Case "seagreen": t2 = "#2e8b57" Case "seashell": t2 = "#fff5ee" Case "sienna~~": t2 = "#a0522d" Case "skyblue~": t2 = "#87ceeb" Case "slateblu": t2 = "#6a5acd" Case "slategra": t2 = "#708090" Case "snow~~~~": t2 = "#fffafa" Case "springgr": t2 = "#00ff7f" Case "steelblu": t2 = "#4682b4" Case "tan~~~~~": t2 = "#d2b48c" Case "thistle~": t2 = "#d8bfd8" Case "tomato~~": t2 = "#ff6347" Case "turquois": t2 = "#40e0d0" Case "violet~~": t2 = "#ee82ee" Case "wheat~~~": t2 = "#f5deb3" Case "whitesmo": t2 = "#f5f5f5" Case "yellowgr": t2 = "#9acd32" End Select If t2 <> "" Then T = t2 Rem RGB-FORM: "rgb(10,20,30)" If Left(T, 3) = "rgb" Then T = Replace(T, "rgb", "") T = Replace(T, "(", "") T = Replace(T, ")", "") v = Split(T) If UBound(v) >= 2 Then Value(1) = 255 - v(0) Value(2) = 255 - v(1) Value(3) = 255 - v(2) End If End If Rem HEX-WERT If Left(T, 1) = "#" Then T = Replace(T, "#", "") T = Right("000000" & T, 6) Value(1) = 255 - val("&H" & Mid(T, 1, 2)) Value(2) = 255 - val("&H" & Mid(T, 3, 2)) Value(3) = 255 - val("&H" & Mid(T, 5, 2)) End If End Sub Rem Rem KLEINE BEHANDLUNGSPROGRAMME Rem =========================== Rem Rem VEKTOR AUSGABEKONVERTIEREN Rem -------------------------- Private Function SVGPVec(v() As Single) As String Rem Rem SVGPVec konvertiert einen Vektor knapp in ein String. Nur 3 Elemente, -9999->"none" Rem Dim s As String If UBound(v) >= 1 Then If v(1) = -9999 Then s = "none" Else s = Format(v(1), "#####000") If UBound(v) >= 2 Then s = s & "," & Format(v(2), "#####000") If UBound(v) >= 3 Then s = s & "," & Format(v(3), "#####000") End If Else s = "----" End If SVGPVec = s End Function Rem Rem FEHLER BEHANDELN FÜR PARSER UND EXEKUTOR Rem ---------------------------------------- Private Sub SVGPErr(i As Long, NText As String, EText As String) Rem Rem SVGPErr protokolliert einen Fehler im globalen Mitteilungsprotokoll SVGMsgProt. Rem Rem Bei positiven i: Parserfehler Token i, Fehlernummer NText, Fehlertext EText. Rem Bei nagativem i: Exekutionsfehler Element -i, Fehlernummer NText, Fehlertext EText. Rem Rem Es wird eine Fehlermitteilung an das globale SVG-Fehlerprotokoll SVGMsgProt angehängt. Rem If i > 1 Then ' Syntaxfehler mit i=Tokennummer SVGMsgProt = SVGMsgProt & NText _ & "/" & Format(i, "0000") _ & "/»" _ & Left(SVGToken(i) & " ", 16) _ & "«: " _ & EText & vbCrLf Else ' Exekutionsfehler. Statt Tokennummer "EXEC" SVGMsgProt = SVGMsgProt & NText _ & "/" & "EXEC" _ & "/" _ & "Element " & Format(0 - i, "00") _ & ": " _ & EText & vbCrLf If NText = "W444" Then ' Beim Pfadfehler Pfaderrortext anhängen und dann löschen SVGMsgProt = SVGMsgProt & SVGPathErrorText SVGPathErrorText = "" End If End If Exit Sub End Sub Rem Rem DOKUMENTATION BEREITSTELLEN Rem =========================== Public Sub SVGDesc(T As String) Rem T = "" T = T & "" & vbCrLf T = T & "BESCHREIBUNG VON VIMAGE-SVG " & vbCrLf T = T & "=========================== " & vbCrLf T = T & vbCrLf T = T & "1. ÜBERBLICK" & vbCrLf T = T & "------------" & vbCrLf T = T & "" & vbCrLf T = T & "VIMAGE-SVG ist ein signographisches Konzept für eine softwareunabhängige Beschrei-" & vbCrLf T = T & "bung beliebiger kartographischer Punktsignaturen." & vbCrLf T = T & "" & vbCrLf T = T & "Die Signaturen werden so beschrieben, als ob sie mit einem Tuschezeichner " & vbCrLf T = T & "oder mit einem Gravierpantographen gezeichnet würden. Anders ausgedrückt: Mit" & vbCrLf T = T & "VIMAGE-SVG lässt sich jede Signatur - die nur irgendwie mit einem Rapidographen" & vbCrLf T = T & "oder mit einer Gravierschablone bescheibbar ist - erzeugen." & vbCrLf T = T & "" & vbCrLf T = T & "Zur Beschreibung wird eine kleine Untermenge des Vektorformates SVG benutzt. " & vbCrLf T = T & "" & vbCrLf T = T & "Die Realisierung erfolgt mit Grundformen Strecke, Rechteck, Kreis, Ellipse, " & vbCrLf T = T & "Polylinie, Polygon und Pfad." & vbCrLf T = T & "" & vbCrLf T = T & "Die Bildauflösung ist immer 1/100 mm. Die Signatur wird standardmäßig in einem" & vbCrLf T = T & "Fixbild der Größe 800*800 aufgebaut, wobei der Zentralpunkt der Signatur mittig" & vbCrLf T = T & "angeordnet wird. Die Standardsignatur kann folglich bis zu 8 x 8 mm groß sein. " & vbCrLf T = T & "" & vbCrLf T = T & "Größere Signaturen sind durch andere Angaben im svg-Element einstellbar. In " & vbCrLf T = T & "jedem Fall wird der Signaturenzentralpunkt mittig angeordnet. " & vbCrLf T = T & "" & vbCrLf T = T & "Es wird immer mit einer runden Zeichenspitze gezeichnet. Diese hat den Durchmesser" & vbCrLf T = T & "stroke-width in 1/100 mm." & vbCrLf T = T & vbCrLf T = T & vbCrLf T = T & "2. ELEMENTE UND ATTRIBUTE IN VIMAGE-SVG" & vbCrLf T = T & "---------------------------------------" & vbCrLf T = T & vbCrLf T = T & " svg width=" & Chr(34) & "n" & Chr(34) & " height=" & Chr(34) & "n" & Chr(34) & " stroke=" & Chr(34) & "c" & Chr(34) & " stroke-width=" & Chr(34) & "n" & Chr(34) & " fill=" & Chr(34) & "c" & Chr(34) & vbCrLf T = T & " g id=" & Chr(34) & "name" & Chr(34) & " stroke=" & Chr(34) & "c" & Chr(34) & " stroke-width=" & Chr(34) & "n" & Chr(34) & " fill=" & Chr(34) & "c" & Chr(34) & vbCrLf T = T & "" & vbCrLf T = T & " line x1=" & Chr(34) & "n" & Chr(34) & " y1=" & Chr(34) & "n" & Chr(34) & " x2=" & Chr(34) & "n" & Chr(34) & " y2=" & Chr(34) & "n" & Chr(34) & " stroke=" & Chr(34) & "c" & Chr(34) & " stroke-width=" & Chr(34) & "n" & Chr(34) & " fill=" & Chr(34) & "c" & Chr(34) & vbCrLf T = T & " rect x=" & Chr(34) & "n" & Chr(34) & " y=" & Chr(34) & "n" & Chr(34) & " width=" & Chr(34) & "n" & Chr(34) & " height=" & Chr(34) & "n" & Chr(34) & " stroke=" & Chr(34) & "c" & Chr(34) & " stroke-width=" & Chr(34) & "n" & Chr(34) & " fill=" & Chr(34) & "c" & Chr(34) & vbCrLf T = T & " circle cx=" & Chr(34) & "n" & Chr(34) & " cy=" & Chr(34) & "n" & Chr(34) & " r=" & Chr(34) & "n" & Chr(34) & " stroke=" & Chr(34) & "c" & Chr(34) & " stroke-width=" & Chr(34) & "n" & Chr(34) & " fill=" & Chr(34) & "c" & Chr(34) & vbCrLf T = T & " ellipse cx=" & Chr(34) & "n" & Chr(34) & " cy=" & Chr(34) & "n" & Chr(34) & " rx=" & Chr(34) & "n" & Chr(34) & " ry=" & Chr(34) & "n" & Chr(34) & " stroke=" & Chr(34) & "c" & Chr(34) & " stroke-width=" & Chr(34) & "n" & Chr(34) & " fill=" & Chr(34) & "c" & Chr(34) & vbCrLf T = T & " polyline points=" & Chr(34) & "list" & Chr(34) & " stroke=" & Chr(34) & "c" & Chr(34) & " stroke-width=" & Chr(34) & "n" & Chr(34) & " fill=" & Chr(34) & "c" & Chr(34) & vbCrLf T = T & " polygon points=" & Chr(34) & "list" & Chr(34) & " stroke=" & Chr(34) & "c" & Chr(34) & " stroke-width=" & Chr(34) & "n" & Chr(34) & " fill=" & Chr(34) & "c" & Chr(34) & " zx=" & Chr(34) & "n" & Chr(34) & " zy=" & Chr(34) & "n" & Chr(34) & vbCrLf T = T & " path data=" & Chr(34) & "pathdata" & Chr(34) & " stroke=" & Chr(34) & "c" & Chr(34) & " stroke-width=" & Chr(34) & "n" & Chr(34) & " fill=" & Chr(34) & "c" & Chr(34) & " zx=" & Chr(34) & "n" & Chr(34) & " zy=" & Chr(34) & "n" & Chr(34) & vbCrLf T = T & vbCrLf T = T & "Für die Attributwerte gilt: " & vbCrLf T = T & " " & vbCrLf T = T & " n ... Zahl, die eine Koordinate oder Länge angibt, z. B. »100«" & vbCrLf T = T & " c ... HTML-Farbangabe z. B. »red«, »#ff8040«, »rgb(23,64,255)« " & vbCrLf T = T & " oder »none« (für nicht füllen)." & vbCrLf T = T & " list ... Koordinatenliste z. B. »0,0 100,0 100,100 100,0« " & vbCrLf T = T & " name ... Aus Kleinbuchstaben, Ziffern und Minusstrich bestehender Name" & vbCrLf T = T & " pathdata ... Pfaddaten" & vbCrLf T = T & vbCrLf T = T & "fill, stroke und stroke-width: Es gibt die 3 Stilattribute fill, stroke und stroke-width." & vbCrLf T = T & "Diese können im Zeichnungselement stehen. Fehlen Angaben, so werden diese dem" & vbCrLf T = T & "vorherigen g-Element (Gruppenelement) entnommen. Fehlen auch diese, so wird " & vbCrLf T = T & "versucht, die Angaben aus dem svg-Element zu ergänzen. Wenn es auch hier " & vbCrLf T = T & "keine Angaben gibt, so gilt fill=" & Chr(34) & "none" & Chr(34) & " stroke=" & Chr(34) & "black" & Chr(34) & " stroke-width=" & Chr(34) & "10" & Chr(34) & "." & vbCrLf T = T & "Die Stilattribute können auch in der Form style=" & Chr(34) & "fill:red;stroke-width=20" & Chr(34) & " angegeben werden." & vbCrLf T = T & vbCrLf T = T & "zx und zy: Pfade und Polygone benötigen zu ihrer Füllung einen Startpunkt." & vbCrLf T = T & "Dieser muss mit den Füllattributen zx und zy bereitgestellt werden." & vbCrLf T = T & vbCrLf T = T & "Beispiel:" & vbCrLf T = T & "" & vbCrLf T = T & "" & vbCrLf T = T & vbCrLf T = T & "Kreise, Ellipsen und Rechtecke können auch ohne die zx/zy gefüllt werden." & vbCrLf T = T & vbCrLf T = T & vbCrLf T = T & "3. DAS PFAD-ELEMENT" & vbCrLf T = T & "-------------------" & vbCrLf T = T & vbCrLf T = T & "Das SVG-Path-Element ist sehr mächtig. Mit ihm kann fast jede beliebige Form erzeugt werden." & vbCrLf T = T & "Es kann folgende Kommandos enthalten:" & vbCrLf T = T & vbCrLf T = T & " M x y Moveto " & vbCrLf T = T & " Z cloZe path " & vbCrLf T = T & " L x y Lineto " & vbCrLf T = T & " H x Horizontal lineto " & vbCrLf T = T & " V y Vertical lineto " & vbCrLf T = T & " C x2 y2 x3 y3 x y Cubic bézier curveto " & vbCrLf T = T & " S x3 y3 x y Smooth cubic bézier curveto " & vbCrLf T = T & " Q x2 y2 x y Quadratic bézier curveto " & vbCrLf T = T & " T x y smooTh quadratic bézier curveto " & vbCrLf T = T & " A r1 r2 a f1 f2 x y elliptical Arcto " & vbCrLf T = T & "" & vbCrLf T = T & "Dabei haben die Parameter folgende Bedeutung:" & vbCrLf T = T & "" & vbCrLf T = T & " x ... Endpunkt X" & vbCrLf T = T & " y ... Endpunkt Y" & vbCrLf T = T & " x2 ... 2. Bézier-Steuerpunkt X (1. Punkt ist der Cursor)" & vbCrLf T = T & " x2 ... 2. Bézier-Steuerpunkt Y (1. Punkt ist der Cursor)" & vbCrLf T = T & " x3 ... 3. Bézier-Steuerpunkt X" & vbCrLf T = T & " x3 ... 3. Bézier-Steuerpunkt Y" & vbCrLf T = T & " r1 ... 1. Ellipsenhalbmesser" & vbCrLf T = T & " r2 ... 2. Ellipsenhalbmesser" & vbCrLf T = T & " a ... Winkel X-Achse-Grosse-Halbachse" & vbCrLf T = T & " f1 ... Large-Arc-Flag, 0 oder 1. Wählt Kurz- oder Langbogen auf Lösungsellipse" & vbCrLf T = T & " f2 ... Sweep-Flag, 0 oder 1. Wählt eine der 2 Lösungsellipsen aus" & vbCrLf T = T & "" & vbCrLf T = T & " Die Werte sind Absolutkoordinaten in Zahlenform. Wenn das Kommando klein " & vbCrLf T = T & " geschrieben wird (m, l, c ... ) werden die Werte als Relativ-" & vbCrLf T = T & " koordinaten relativ zum aktuellen Cursor interpretiert. " & vbCrLf T = T & "" & vbCrLf T = T & " Die smooth-Bezierkurven nehmen als 2. Steuerpunkt den vorletzten Steuer- " & vbCrLf T = T & " punkt des vorhergehenden Kommandos um den letzten Endpunkt gespiegelt an. " & vbCrLf T = T & "" & vbCrLf T = T & " Beispiel für ein Pfadkommando: »M 100,100 L 0,100 L 0,0 L 100,0 Z«" & vbCrLf T = T & "" & vbCrLf T = T & " Bei mehreren aufeinanderfolgenden gleichen Kommandos kann der Kommandobuchstabe" & vbCrLf T = T & " auch weggelassen werden:" & vbCrLf T = T & "" & vbCrLf T = T & " Beispiel: »M 100,100 L 0,100 0,0 100,0 Z«" & vbCrLf T = T & "" & vbCrLf T = T & "" & vbCrLf T = T & "4. SONSTIGES" & vbCrLf T = T & "------------" & vbCrLf T = T & "" & vbCrLf T = T & "Vimage-SVG ist eine stark vereinfachte Untermenge des Original-SVG." & vbCrLf T = T & "" & vbCrLf T = T & "(Implementierter Standard: SVG 1.0 www.w3.org/TR/2001/REC-SVG-20010904/svg10.dtd)" & vbCrLf T = T & "" & vbCrLf T = T & "Damit die Dateien in allen Internet-Browsern korrekt angezeigt werden, sollten" & vbCrLf T = T & "die Zeichnungselemente wie folgt in je einem svg- und g-Element gekapselt werden:" & vbCrLf T = T & "" & vbCrLf T = T & "" & vbCrLf T = T & "" & vbCrLf T = T & "" & vbCrLf T = T & " " & vbCrLf T = T & " " & vbCrLf T = T & " " & vbCrLf T = T & " " & vbCrLf T = T & " " & vbCrLf T = T & "" & vbCrLf T = T & " " & vbCrLf T = T & "" & vbCrLf T = T & "" & vbCrLf T = T & "" & vbCrLf T = T & "" & vbCrLf T = T & "" & vbCrLf T = T & "Vimage-SVG kann in geklammerten Kommentar enthalten. Das ist in manchen" & vbCrLf T = T & "SVG-Implementationen nicht der Fall." & vbCrLf T = T & "" & vbCrLf T = T & "In Vimage-SVG müssen Tags nicht ungedingt abgeschlossen werden, das wird aber in manchen" & vbCrLf T = T & "SVG-Implementationen erwartet. Also nach immer ein -Tag setzen." & vbCrLf T = T & "" & vbCrLf T = T & "Die Füllattribute zx und zy werden nur in Vimage-SVG benötigt und sind kein Bestandteil des SVG-Standards." & vbCrLf T = T & "" & vbCrLf T = T & "[Ende der Dokumentation von Vimage-SVG] " & vbCrLf End Sub