La libreria TLTFormat
Dopo aver pensato al concetto, è ora di venire alle mani, per modo di dire, e scrivere il codice. Questo namespace espone tre classi principali:
- TextChunk : rappresenta un pezzo di testo formattato. Più nuclei come questo formano un documento di testo formattato. Io non ho allegato nessun programma completo che utilizzi questo formato, perchè non era nelle mie intenzioni, ma questi pezzetti potrebbero venire estrapolati da una RichTextBox
- Writer : una volta immagazzinati tutti i TextChunk nella lista Chunks, li scrive su file
- Reader : legge un file e riempie la lista Chunk
Imports System.IOImports System.IO.CompressionImports System.Text.UTF8EncodingNamespace TLTFormat 'Questa classe rappresenta un chunk di testo e tutte le 'informazioni di formattazione ad esso connesse Public Class TextChunk 'Enumeratore per l'allineamento. Ne esiste già uno, 'ma non ha il campo Giustificato Public Enum Alignment Left Right Center JustifyEnd Enum 'Grassetto Private _IsBoldAs Boolean = False 'Corsivo Private _IsItalicAs Boolean = False 'Sottolineato Private _IsUnderlinedAs Boolean = False 'Colore Private _ColorAs Color = Drawing.Color.Black 'Nome del font Private _FontNameAs String = "TimesNew Roman" 'Dimensione Private _SizeAs Byte = 12 'Testo del chunk Private _TextAs String 'Allineamento Private _AlignAs Alignment = Alignment.LeftPublic Property IsBold()As Boolean Get Return _IsBoldEnd Get Set (ByVal ValueAs Boolean ) _IsBold = ValueEnd Set End Property Public Property IsItalic()As Boolean Get Return _IsItalicEnd Get Set (ByVal ValueAs Boolean ) _IsItalic = ValueEnd Set End Property Public Property IsUnderlined()As Boolean Get Return _IsUnderlinedEnd Get Set (ByVal ValueAs Boolean ) _IsUnderlined = ValueEnd Set End Property Public Property Color()As ColorGet Return _ColorEnd Get Set (ByVal ValueAs Color) _Color = ValueEnd Set End Property Public Property FontName()As String Get Return _FontNameEnd Get Set (ByVal ValueAs String ) _FontName = ValueEnd Set End Property Public Property Size()As Byte Get Return _SizeEnd Get Set (ByVal ValueAs Byte ) _Size = ValueEnd Set End Property Public Property Text()As String Get Return _TextEnd Get Set (ByVal ValueAs String ) _Text = ValueEnd Set End Property Public Property Align()As AlignmentGet Return _AlignEnd Get Set (ByVal valueAs Alignment) _Align = valueEnd Set End Property 'Questa proprietà è speciale. 'Permette di ottenere in un solo colpo tutte le 'caratteristiche di formattazione del chunk 'restituendo una classe font completa Public ReadOnly Property Font()As FontGet Dim StyleAs FontStyle 'Costruiamo lo stile del font a poco a poco, 'poiché questo è un enumeratore su bit If Me .IsBoldThen Style = StyleOr FontStyle.BoldEnd If If Me .IsItalicThen Style = StyleOr FontStyle.ItalicEnd If If Me .IsUnderlinedThen Style = StyleOr FontStyle.UnderlineEnd If Return New Font(Me .FontName,Me .Size, Style)End Get End Property End Class 'Questa classe ha il compito di scrivere su un file 'il testo formattato secondo le specifiche TLT Public Class Writer 'Questa collezione conterrà una lista di 'tutti i piccoli pezzettini di testo che si devono 'scrivere Private _ChunksAs New List(Of TextChunk)Public ReadOnly Property Chunks()As List(Of TextChunk)Get Return _ChunksEnd Get End Property 'Questa funzione serve a comprimere il testo Private Function Compress(ByVal StrAs String )As Byte() 'Usiamo dei MemoryStream per due motivi: '- Il testo proviene dall'applicazione, non da un file, ed è 'sottoforma di stringa. '- Non possiamo non usare uno stream, perchè la classe 'di compressione lo richiede espressamente 'Lo stream che legge i dati dalla stringa Dim InputAs MemoryStream 'Lo stream di scrittura associato al file compresso Dim OutputAs MemoryStream 'Lo stream compresso che scrive i dati codificati per mezzo 'dell'output stream Dim ZippedAs DeflateStream 'Risultato della compressione Dim Result(), Buffer()As Byte 'Inizializza lo stream di input Input =New MemoryStream(UTF8.GetBytes(Str)) 'Inizializza lo stream di output Output =New MemoryStream() 'Inizializza lo zipper Zipped =New DeflateStream(Output, CompressionMode.Compress) ReDim Buffer(Input.Length - 1) Input.Read(Buffer, 0, Input.Length) Zipped.Write(Buffer, 0, Buffer.Length) 'Trasferisce dati compressi sullo stream Zipped.Flush() ReDim Result(Output.Length - 1) Output.Seek(0, SeekOrigin.Begin) Output.Read(Result, 0, Output.Length) 'Quindi chiude tutti gli stream Zipped.Close() Output.Close() Input.Close()Return ResultEnd Function Public Sub Write(ByVal FileAs String ) 'Il writer principale Dim WriterAs New BinaryWriter(New FileStream(File, FileMode.Create)) 'Scrive TLT Dim b()As Byte = UTF8.GetBytes("TLT") Writer.Write(UTF8.GetBytes("TLT")) 'Scrive ogni chunk For Each CAs TextChunkIn Me .Chunks 'Questo byte contiene tutte le informazione, come 'descritto dalle specificazioni che ho inventato Dim FlagsAs Byte = 0 'Aggiungere 128 significa impostare a 1 il primo bit 'Infatti 128 in binario è 10000000 If C.IsBoldThen Flags += 128End If If C.IsItalicThen Flags += 64End If If C.IsUnderlinedThen Flags += 32End If 'Se il colore non è quello predefinito, 'imposta il bit su 1 If C.Color <> Color.BlackThen Flags += 16End If 'Lo stesso per la grandezza If C.Size <> 12Then Flags += 8End If 'E per il font If C.FontName <> "TimesNew Roman"Then Flags += 4End If 'Poi controlla l'allineamento Select Case C.AlignCase TextChunk.Alignment.Left Flags += 0 'Non sono matto, eh! Case TextChunk.Alignment.Right Flags += 1Case TextChunk.Alignment.Center Flags += 2Case TextChunk.Alignment.Justify Flags += 3End Select 'Scrive i flags Writer.Write(CByte(Flags)) 'Ora, se il colore non è quello predefinito, 'lo scrive If C.Color <> Color.BlackThen 'In ordine, A, R, G, B Writer.Write(C.Color.A) Writer.Write(C.Color.R) Writer.Write(C.Color.G) Writer.Write(C.Color.B)End If 'Poi scrive la grandezza If C.Size <> 12Then Writer.Write(C.Size)End If 'E infine il nome del font If C.FontName <> "TimesNew Roman"Then Writer.Write(UTF8.GetBytes(C.FontName)) Writer.Write(CByte(0)) 'Byte nullo End If 'Poi la dimensione e il testo Dim Bytes()As Byte = UTF8.GetBytes(C.Text) Writer.Write(CInt(Bytes.Length)) Writer.Write(Bytes)Next Writer.Close()End Sub End Class Public Class ReaderPrivate _ChunksAs New List(Of TextChunk)Public ReadOnly Property Chunks()As List(Of TextChunk)Get Return _ChunksEnd Get End Property Public Sub Read(ByVal FileAs String ) 'Lo stream di lettura Dim ReaderAs New BinaryReader(New FileStream(File, FileMode.Open)) 'Legge i primi 3 bytes Dim Buffer(2)As Byte Buffer = Reader.ReadBytes(3) 'Se non sono "TLT", allora esce If UTF8.GetString(Buffer) <> "TLT"Then Reader.Close()Exit Sub End If Do 'Legge il byte dei flags Dim FlagsAs Byte = Reader.ReadByteDim CAs New TextChunk 'Estrapola i dati C.IsBold = ((FlagsAnd 128) = 128) C.IsItalic = ((FlagsAnd 64) = 64) C.IsUnderlined = ((FlagsAnd 32) = 32)If (FlagsAnd 16) = 16Then 'In ordine, A, R, G, B 'Dopo tutto, essendo 3 bytes, li si 'può trattare come un Int32 Dim ArgbAs Int32 Argb = Reader.ReadInt32 C.Color = Color.FromArgb(Argb)Else C.Color = Color.BlackEnd If 'Poi scrive la grandezza If (FlagsAnd 8) = 8Then C.Size = Reader.ReadByteElse C.Size = 12End If 'E infine il nome del font If (FlagsAnd 4) = 4Then Dim TempAs New List(Of Byte )Dim BAs Byte = Reader.ReadByte 'Legge i bytes fino ad incontrare il 'byte nullo di fine stringa Do While B <> 0 Temp.Add(B) B = Reader.ReadByteLoop C.FontName = UTF8.GetString(Temp.ToArray)End If If (FlagsAnd 2) = 2Then If (FlagsAnd 1) = 1Then '11 - giustificato C.Align = TextChunk.Alignment.JustifyElse '10 - centrato C.Align = TextChunk.Alignment.CenterEnd If Else If (FlagsAnd 1) = 1Then '01 - destra C.Align = TextChunk.Alignment.RightElse '00 - sinistra C.Align = TextChunk.Alignment.LeftEnd If End If 'Poi la dimensione e il testo Dim SizeAs Int32 Size = Reader.ReadInt32 Buffer = Reader.ReadBytes(Size) C.Text = UTF8.GetString(Buffer)Me .Chunks.Add(C)Loop While Reader.BaseStream.Position < Reader.BaseStream.Length Reader.Close()End Sub End Class End Namespace
The Totem's Lair - Copyright (C) 2009
È vietata la riproduzione sia totale che parziale del sito.



