public static bool CheckWorldExistsByGenre(Guid worldId, Genres genres) { string bucket = BokuGame.MyWorldsPath; if (genres != 0) { bucket = Utils.FolderNameFromFlags(genres); if (bucket == null) { return(false); } } string fullPath = BokuGame.Settings.MediaPath + bucket + worldId.ToString() + @".Xml"; StorageSource sources = StorageSource.All; if ((genres & Genres.Downloads) != 0) { sources = StorageSource.UserSpace; } return(Storage4.FileExists(fullPath, sources)); }
/// <summary> /// Update the level's metadata on disk. /// Does not change the level's timestamp. /// </summary> /// <param name="level"></param> public static void UpdateWorldMetadata(LevelMetadata level) { try { string bucket = Utils.FolderNameFromFlags(level.Genres); string fullPath = BokuGame.Settings.MediaPath + bucket + level.WorldId.ToString() + @".Xml"; Xml.XmlWorldData xml = XmlWorldData.Load(fullPath, XnaStorageHelper.Instance); if (xml != null) { level.ToXml(xml); bool isDownload = (level.Genres & Genres.Downloads) != 0; // Manage the stream ourselves so avoid level timestamp being changed. Stream stream = Storage4.OpenWrite(fullPath); xml.Save(stream, isDownload); Storage4.Close(stream); } } catch (Exception e) { Debug.WriteLine(e.Message); } }
/// <summary> /// Update the level's xml on disk. /// Does not change the level's timestamp. /// </summary> /// <param name="level"></param> public static void UpdateWorldXml(XmlWorldData xml) { try { string bucket = Utils.FolderNameFromFlags((Genres)xml.genres); string fullPath = BokuGame.Settings.MediaPath + bucket + xml.id.ToString() + @".Xml"; //make sure the world exists if (!Storage4.FileExists(fullPath, StorageSource.All)) { return; } if (xml != null) { bool isDownload = (xml.genres & (int)Genres.Downloads) != 0; // Manage the stream ourselves so avoid level timestamp being changed. Stream stream = Storage4.OpenWrite(fullPath); xml.Save(stream, isDownload); Storage4.Close(stream); } } catch (Exception e) { Debug.WriteLine(e.Message); } }
private void GotThumbnail(AsyncResult ar) { AsyncResult_Thumbnail result = (AsyncResult_Thumbnail)ar; LevelMetadata level = (LevelMetadata)result.Param; LevelBrowserState state = (LevelBrowserState)level.BrowserState; if (result.Success) { MemoryStream stream = new MemoryStream(result.ThumbnailBytes); level.Thumbnail.Texture = Storage4.TextureLoad(stream); level.Thumbnail.Loading = false; } else { // TODO: Set thumbnail to use missing icon. } if (state.thumbnailCallback != null) { state.thumbnailCallback(level); } state.thumbnailCallback = null; thumbnailLoadOpCount -= 1; }
/// <summary> /// Creates a StorageFile in the temp folder. /// </summary> /// <returns></returns> public static StorageFile GetTempStorageFile() { Guid guid = Guid.NewGuid(); string filename = guid.ToString() + ".tmp"; StorageFile file = Storage4.CreateStorageFile(TempFolder, filename); return(file); }
private void CompleteThumbnail(LevelMetadata level) { level.Thumbnail.Loading = false; if (level.ThumbnailBytes != null) { MemoryStream stream = new MemoryStream(level.ThumbnailBytes); level.Thumbnail.Texture = Storage4.TextureLoad(stream); level.ThumbnailBytes = null; } }
static public bool TextureSaveAsPng(Texture2D tex, string name) { if (tex != null) { Stream stream = Storage4.OpenWrite(name); tex.SaveAsPng(stream, tex.Width, tex.Height); stream.Close(); return(true); } return(false); }
private bool IsAlreadyDownloaded(LevelMetadata level) { string filename = BokuGame.Settings.MediaPath + BokuGame.DownloadsPath + level.WorldId.ToString() + @".Xml"; if (Storage4.FileExists(filename, StorageSource.UserSpace)) { XmlWorldData xml = XmlWorldData.Load(filename, XnaStorageHelper.Instance); if (xml != null) { LevelMetadata local = LevelMetadata.CreateFromXml(xml); return( local.WorldId == level.WorldId && local.Creator == level.Creator && local.LastWriteTime >= level.LastWriteTime); } } return(false); }
/// <summary> /// Loads Actors.xml and initializes the list of static actors. /// </summary> /// <remarks> /// The actors' model and xml file isn't loaded until LoadModels is called. /// </remarks> public static void LoadActors() { if (Storage4.FileExists(XmlActorsListFileName, StorageSource.TitleSpace)) { // Read our actor list from file var stream = Storage4.OpenRead(XmlActorsListFileName, StorageSource.TitleSpace); var serializer = new XmlSerializer(typeof(XmlActorsList)); var xmlActors = serializer.Deserialize(stream) as XmlActorsList; Storage4.Close(stream); if (xmlActors != null) { for (int i = 0; i < xmlActors.Actors.Length; i++) { var xmlStaticActor = xmlActors.Actors[i]; Actors.Add(xmlStaticActor.NonLocalizedName, new StaticActor(xmlStaticActor)); } } } else { Debug.Assert(false, "Missing actor file."); } }
} // end of ScrubTerrainFiles() /// <summary> /// Deletes the given terrain file but only after verifying that no world is using it. /// It any world is found that is using the file then it is not deleted. /// /// Note this still isn't perfect since when a level is deleted, the terrain file may still be left /// in the undo stack and hence not deleted. No biggy. It's better than deleting too much and it's /// much quicker than the above ScrubTerrainFiles(). /// </summary> /// <param name="terrainFile"></param> void DeleteTerrainFile(string terrainFile) { string[] undoFiles = Storage4.GetFiles(BokuGame.Settings.MediaPath + BokuGame.UnDoPath, @"*.Xml", StorageSource.UserSpace); string[] myWorldsFiles = Storage4.GetFiles(BokuGame.Settings.MediaPath + BokuGame.MyWorldsPath, @"*.Xml", StorageSource.UserSpace); string[] starterWorldsFiles = Storage4.GetFiles(BokuGame.Settings.MediaPath + BokuGame.BuiltInWorldsPath, @"*.Xml", StorageSource.TitleSpace); string[] downloadsFiles = Storage4.GetFiles(BokuGame.Settings.MediaPath + BokuGame.DownloadsPath, @"*.Xml", StorageSource.UserSpace); /// Undo/Resume files. We might have to fall back on these if the user deletes the /// world they are editing and then back back to it. if (undoFiles != null) { for (int i = 0; i < undoFiles.Length; ++i) { string filename = undoFiles[i]; XmlWorldData xmlWorldData = XmlWorldData.Load(filename, XnaStorageHelper.Instance); if (xmlWorldData == null || xmlWorldData.xmlTerrainData2 == null) { continue; } if (xmlWorldData.xmlTerrainData2.virtualMapFile == terrainFile) { // Found it, don't delete. return; } } } // MyWorlds if (myWorldsFiles != null) { for (int i = 0; i < myWorldsFiles.Length; ++i) { string filename = myWorldsFiles[i]; XmlWorldData xmlWorldData = XmlWorldData.Load(filename, XnaStorageHelper.Instance); if (xmlWorldData == null || xmlWorldData.xmlTerrainData2 == null) { continue; } if (xmlWorldData.xmlTerrainData2.virtualMapFile == terrainFile) { // Found it, don't delete. return; } } } // BuiltInWorlds if (starterWorldsFiles != null) { for (int i = 0; i < starterWorldsFiles.Length; ++i) { try { string filename = starterWorldsFiles[i]; XmlWorldData xmlWorldData = XmlWorldData.Load(filename, XnaStorageHelper.Instance); if (xmlWorldData == null || xmlWorldData.xmlTerrainData2 == null) { continue; } if (xmlWorldData.xmlTerrainData2.virtualMapFile == terrainFile) { // Found it, don't delete. return; } } catch { } } } // Downloads if (downloadsFiles != null) { for (int i = 0; i < downloadsFiles.Length; ++i) { string filename = downloadsFiles[i]; XmlWorldData xmlWorldData = XmlWorldData.Load(filename, XnaStorageHelper.Instance); if (xmlWorldData == null || xmlWorldData.xmlTerrainData2 == null) { continue; } if (xmlWorldData.xmlTerrainData2.virtualMapFile == terrainFile) { // Found it, don't delete. return; } } } // Nothing was found using this terrain file so we can delete it. try { terrainFile = Path.Combine(BokuGame.Settings.MediaPath, terrainFile); Storage4.Delete(terrainFile); } catch (Exception e) { if (e != null) { } } } // end of DeleteTerrainFile()
public override Stream OpenRead(string filename) { return(Storage4.OpenRead(filename, StorageSource.All)); }
public override Stream OpenRead(string filename, int flags) { return(Storage4.OpenRead(filename, (StorageSource)flags)); }
public static bool WriteWorldDataPacketToDisk(BokuShared.Wire.WorldDataPacket packet, byte[] thumbnailBytes, DateTime timeStamp) { Stream file = null; try { // Check for presence of the essential world data if (packet == null) { return(false); } if (packet.WorldXmlBytes == null) { return(false); } if (packet.StuffXmlBytes == null) { return(false); } // Read in contents of world xml buffer Xml.XmlWorldData xmlWorldData = Xml.XmlWorldData.Load(packet.WorldXmlBytes); if (xmlWorldData == null) { return(false); } xmlWorldData.overrideLastWriteTime = timeStamp; xmlWorldData.id = packet.WorldId; xmlWorldData.stuffFilename = BokuGame.DownloadsStuffPath + xmlWorldData.Filename; // Non-essential file: Write thumbnail image to disk if (thumbnailBytes != null) { string ext = Storage4.TextureExt(thumbnailBytes); string thumbFilename = xmlWorldData.GetImageFilenameWithoutExtension() + "." + ext; file = Storage4.OpenWrite(BokuGame.Settings.MediaPath + BokuGame.DownloadsPath + thumbFilename); file.Write(thumbnailBytes, 0, thumbnailBytes.Length); Storage4.Close(file); file = null; } // Cubeworld virtual terrain map if (packet.VirtualMapBytes != null) { file = Storage4.OpenWrite(BokuGame.Settings.MediaPath + xmlWorldData.xmlTerrainData2.virtualMapFile); file.Write(packet.VirtualMapBytes, 0, packet.VirtualMapBytes.Length); Storage4.Close(file); file = null; } // Write stuff xml to disk file = Storage4.OpenWrite(BokuGame.Settings.MediaPath + xmlWorldData.stuffFilename); file.Write(packet.StuffXmlBytes, 0, packet.StuffXmlBytes.Length); Storage4.Close(file); file = null; // Clear virtual genre bits because they should not be stored. xmlWorldData.genres &= ~(int)Genres.Virtual; xmlWorldData.genres &= ~(int)Genres.Favorite; // Serialize xmlWorldData to disk string fullPath = BokuGame.Settings.MediaPath + BokuGame.DownloadsPath + xmlWorldData.Filename; xmlWorldData.Save(fullPath, XnaStorageHelper.Instance); Instrumentation.RecordEvent(Instrumentation.EventId.LevelDownloaded, xmlWorldData.name); return(true); } catch { if (file != null) { Storage4.Close(file); } return(false); } }
public override Stream OpenWrite(string filename) { return(Storage4.OpenWrite(filename)); }
public static BokuShared.Wire.WorldPacket ReadWorldPacketFromDisk(string worldFullPathAndName, string bucket) { BokuShared.Wire.WorldPacket packet = null; Stream file = null; try { string localLevelPath = BokuGame.Settings.MediaPath + bucket; string worldFilename = Path.GetFileName(worldFullPathAndName); // Read contents of world xml to retrieve the names of the dependent // files we need to upload Xml.XmlWorldData xmlWorldData = XmlWorldData.Load(localLevelPath + worldFilename, XnaStorageHelper.Instance); if (xmlWorldData == null) { return(null); } // Clear virtual genre bits in case they got saved (server clears them too). xmlWorldData.genres &= ~(int)Genres.Virtual; packet = new BokuShared.Wire.WorldPacket(); packet.Info.WorldId = packet.Data.WorldId = xmlWorldData.id; packet.Info.Name = xmlWorldData.name; packet.Info.Description = xmlWorldData.description; packet.Info.Creator = xmlWorldData.creator; packet.Info.IdHash = ""; packet.Info.Genres = xmlWorldData.genres; string imageFileName = xmlWorldData.GetImageFilenameWithoutExtension(); // VirtualMap file = Storage4.OpenRead(BokuGame.Settings.MediaPath + xmlWorldData.xmlTerrainData2.virtualMapFile, StorageSource.All); packet.Data.VirtualMapBytes = new byte[file.Length]; file.Read(packet.Data.VirtualMapBytes, 0, (int)file.Length); Storage4.Close(file); // Stuff xml file = Storage4.OpenRead(BokuGame.Settings.MediaPath + xmlWorldData.stuffFilename, StorageSource.All); packet.Data.StuffXmlBytes = new byte[file.Length]; file.Read(packet.Data.StuffXmlBytes, 0, (int)file.Length); Storage4.Close(file); // Optional: don't worry if we don't have a thumbnail image. try { file = null; file = Storage4.TextureFileOpenRead(localLevelPath + imageFileName); if (file != null) { packet.Info.ThumbnailBytes = new byte[file.Length]; file.Read(packet.Info.ThumbnailBytes, 0, (int)file.Length); Storage4.Close(file); } } catch { } // Try To load Snapshot image. try { file = null; file = Storage4.TextureFileOpenRead(localLevelPath + imageFileName, Storage4.TextureFileType.jpg); if (file != null) { packet.Info.ScreenshotBytes = new byte[file.Length]; file.Read(packet.Info.ScreenshotBytes, 0, (int)file.Length); Storage4.Close(file); } } catch { } // We've successfully read all required files. We may now upload them to the server. file = Storage4.OpenRead(localLevelPath + worldFilename, StorageSource.All); packet.Data.WorldXmlBytes = new byte[file.Length]; file.Read(packet.Data.WorldXmlBytes, 0, (int)file.Length); Storage4.Close(file); Instrumentation.RecordEvent(Instrumentation.EventId.LevelUploaded, xmlWorldData.name); } catch { if (file != null) { Storage4.Close(file); } packet = null; } return(packet); }
} // end of XmlHelpTextData ReadFromXml() private static XmlHelpTextData Load(string filename) { XmlHelpTextData data = null; Stream stream = null; // First try with StorageSoruce.All so we get the version downloaded // from the servers. If that fails then get the TitleSpace version. try { stream = Storage4.OpenRead(filename, StorageSource.All); XmlSerializer serializer = new XmlSerializer(typeof(XmlHelpTextData)); data = (XmlHelpTextData)serializer.Deserialize(stream); } catch (Exception e) { data = null; if (e != null) { #if !NETFX_CORE string message = e.Message; if (e.InnerException != null) { message += e.InnerException.Message; } System.Windows.Forms.MessageBox.Show( message, "Error reading " + filename, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error ); #endif } } finally { Storage4.Close(stream); } // If we don't have data. Delete the server version of // the file and try loading the TitleSpace version. if (data == null) { // Don't delete the server version since this might actually be someone // trying to do a localization. //Storage4.Delete(filename); try { stream = Storage4.OpenRead(filename, StorageSource.TitleSpace); XmlSerializer serializer = new XmlSerializer(typeof(XmlHelpTextData)); data = (XmlHelpTextData)serializer.Deserialize(stream); } catch (Exception) { data = null; } finally { Storage4.Close(stream); } } return(data); } // end of XmlHelpTextData Load()
/// <summary> /// Returns true on success, false if failed. /// </summary> public bool ReadFromXml(string filename) { bool success = true; // Fix up the filename with the full path. var defaultFile = Path.Combine(Localizer.DefaultLanguageDir, filename); // Read the Xml file into local data. XmlHelpTextData data = Load(defaultFile); // Build a dictionary with the default info var dict = new Dictionary <string, TweakScreenHelp.HelpText>(data.helpText.Count); foreach (var helpText in data.helpText) { dict[helpText.id] = helpText; } // Is our run-time local language different from the default? if (!Localizer.IsLocalDefault) { var localPath = Localizer.LocalLanguageDir; // Do we have a directory for the local language? if (localPath != null) { var localFile = Path.Combine(localPath, filename); if (Storage4.FileExists(localFile, StorageSource.All)) { var localData = Load(localFile); var localDict = new Dictionary <string, TweakScreenHelp.HelpText>(localData.helpText.Count); foreach (var helpText in localData.helpText) { localDict[helpText.id] = helpText; } // Replace as much of the default data as we can with localized data var keys = dict.Keys.ToArray(); foreach (var key in keys) { if (localDict.ContainsKey(key)) { if (Localizer.ShouldReportMissing && localDict[key].desc.Equals(dict[key].desc, StringComparison.OrdinalIgnoreCase)) { Localizer.ReportIdentical(filename, key); } dict[key] = localDict[key]; } else { Localizer.ReportMissing(filename, key); } } data.helpText = dict.Values.ToList(); } else { Localizer.ReportMissing(filename, "CAN'T FIND FILE!"); } } else { Localizer.ReportMissing(localPath, "CAN'T FIND PATH FOR THIS LANGUAGE!"); } } if (data == null) { success = false; } else { this.helpText = data.helpText; } return(success); } // end of XmlHelpTextData ReadFromXml()
private void ScrubTerrainFiles() { // Build a list of all terrain files in user storage. // For each world in local storage (all three bins) // get the XmlWorldData file // from the XmlWorldData file, get the terrain filename // remove that filename from the list // // Any terrain filenames still on the list should be deleted // since they're no longer referenced by any files. string[] terrainFiles = Storage4.GetFiles(BokuGame.Settings.MediaPath + BokuGame.TerrainPath, @"*.raw", StorageSource.UserSpace); // If nothing to scrub, just return. if (terrainFiles == null) { return; } string[] undoFiles = Storage4.GetFiles(BokuGame.Settings.MediaPath + BokuGame.UnDoPath, @"*.Xml", StorageSource.UserSpace); string[] myWorldsFiles = Storage4.GetFiles(BokuGame.Settings.MediaPath + BokuGame.MyWorldsPath, @"*.Xml", StorageSource.UserSpace); string[] starterWorldsFiles = Storage4.GetFiles(BokuGame.Settings.MediaPath + BokuGame.BuiltInWorldsPath, @"*.Xml", StorageSource.TitleSpace); string[] downloadsFiles = Storage4.GetFiles(BokuGame.Settings.MediaPath + BokuGame.DownloadsPath, @"*.Xml", StorageSource.UserSpace); /// Undo/Resume files. We might have to fall back on these if the user deletes the /// world they are editing and then back back to it. if (undoFiles != null) { for (int i = 0; i < undoFiles.Length; ++i) { string filename = undoFiles[i]; XmlWorldData xmlWorldData = XmlWorldData.Load(filename, XnaStorageHelper.Instance); if (xmlWorldData == null) { continue; } if (xmlWorldData.xmlTerrainData2 != null) { string terrainName = Path.Combine(Storage4.UserLocation, BokuGame.Settings.MediaPath, xmlWorldData.xmlTerrainData2.virtualMapFile); for (int j = 0; j < terrainFiles.Length; ++j) { if (terrainName == terrainFiles[j]) { // Remove this file. terrainFiles[j] = null; break; } } } } } // MyWorlds if (myWorldsFiles != null) { for (int i = 0; i < myWorldsFiles.Length; ++i) { string filename = myWorldsFiles[i]; XmlWorldData xmlWorldData = XmlWorldData.Load(filename, XnaStorageHelper.Instance); if (xmlWorldData == null) { continue; } if (xmlWorldData.xmlTerrainData2 != null) { string terrainName = Path.Combine(Storage4.UserLocation, BokuGame.Settings.MediaPath, xmlWorldData.xmlTerrainData2.virtualMapFile); for (int j = 0; j < terrainFiles.Length; ++j) { if (terrainName == terrainFiles[j]) { // Remove this file. terrainFiles[j] = null; break; } } } } } // BuiltInWorlds if (starterWorldsFiles != null) { for (int i = 0; i < starterWorldsFiles.Length; ++i) { try { string filename = starterWorldsFiles[i]; XmlWorldData xmlWorldData = XmlWorldData.Load(filename, XnaStorageHelper.Instance); if (xmlWorldData == null) { continue; } if (xmlWorldData.xmlTerrainData2 != null) { string terrainName = Path.Combine(Storage4.UserLocation, BokuGame.Settings.MediaPath, xmlWorldData.xmlTerrainData2.virtualMapFile); for (int j = 0; j < terrainFiles.Length; ++j) { if (terrainName == terrainFiles[j]) { // Remove this file. terrainFiles[j] = null; break; } } } } catch { } } } // Downloads if (downloadsFiles != null) { for (int i = 0; i < downloadsFiles.Length; ++i) { string filename = downloadsFiles[i]; XmlWorldData xmlWorldData = XmlWorldData.Load(filename, XnaStorageHelper.Instance); if (xmlWorldData == null) { continue; } if (xmlWorldData.xmlTerrainData2 != null) { string terrainName = Path.Combine(Storage4.UserLocation, BokuGame.Settings.MediaPath, xmlWorldData.xmlTerrainData2.virtualMapFile); for (int j = 0; j < terrainFiles.Length; ++j) { if (terrainName == terrainFiles[j]) { // Remove this file. terrainFiles[j] = null; break; } } } } } int deleteCount = 0; // Now, anything that's left in the list should be fair game for deletion. for (int i = 0; i < terrainFiles.Length; i++) { if (terrainFiles[i] != null) { if (Storage4.FileExists(terrainFiles[i], StorageSource.UserSpace)) { if (Storage4.Delete(terrainFiles[i])) { deleteCount += 1; } } } } //System.Diagnostics.Debug.WriteLine(String.Format("Scrubbed {0} terrain files", deleteCount)); } // end of ScrubTerrainFiles()
/// <summary> /// Delete a level from the local system. Returns false if not yet initialized. /// </summary> /// <param name="worldId"></param> /// <param name="callback"></param> /// <param name="param"></param> /// <returns></returns> public bool StartDeletingLevel( Guid worldId, Genres bucket, BokuAsyncCallback callback, object param) { bool deleted = false; bucket &= Genres.SharableBins; // Verify exactly one bucket is specified Debug.Assert(bucket != 0); Debug.Assert((int)bucket == int.MinValue || MyMath.IsPowerOfTwo((int)bucket)); string worldFilename = null; string stuffFilename = null; string thumbFilename = null; LevelMetadata record = null; string stuffPath = String.Empty; string worldPath = String.Empty; if (0 != (bucket & Genres.MyWorlds)) { stuffPath = BokuGame.MyWorldsStuffPath; worldPath = BokuGame.MyWorldsPath; } else if (0 != (bucket & Genres.Downloads)) { stuffPath = BokuGame.DownloadsStuffPath; worldPath = BokuGame.DownloadsPath; } lock (Synch) { for (int i = 0; i < allLevels.Count; ++i) { record = allLevels[i]; if (record.WorldId == worldId && (record.Genres & bucket) == bucket) { worldFilename = Path.Combine(BokuGame.Settings.MediaPath, worldPath + worldId.ToString() + @".Xml"); stuffFilename = Path.Combine(BokuGame.Settings.MediaPath, stuffPath + worldId.ToString() + @".Xml"); thumbFilename = Path.Combine(BokuGame.Settings.MediaPath, worldPath + worldId.ToString()); // Need to get the terrain file before we delete the main file. BUT the terrain should be // deleted after, otherwise the usage test will find the main file and always thing that // the terrain file is in use. string terrainFilename = null; try { // Only delete terrain file if no longer referenced. XmlWorldData xmlWorldData = XmlWorldData.Load(worldFilename, XnaStorageHelper.Instance); terrainFilename = xmlWorldData.xmlTerrainData2.virtualMapFile; } catch { } // Note : Delete() handles non-existent files just fine. Storage4.Delete(worldFilename); Storage4.Delete(stuffFilename); Storage4.Delete(thumbFilename + @".dds"); Storage4.Delete(thumbFilename + @".jpg"); Storage4.Delete(thumbFilename + @".png"); // Only deletes terrain file if no other world is using it. (including autosaves) DeleteTerrainFile(terrainFilename); LevelMetadata level = allLevels[i]; allLevels.RemoveAt(i); LevelRemoved_Synched(level); deleted = true; break; } } } AsyncResult result = new AsyncResult(); result.Success = deleted; result.Param = param; result.Seconds = 0; if (callback != null) { callback(result); } return(deleted); }
public static void Init() { // // Mirroring data. // string[] mirrorData = Storage4.ReadAllLines(@"Content\Xml\Unicode\BidiMirroring.txt", StorageSource.TitleSpace); if (mirrorData != null) { for (int i = 0; i < mirrorData.Length; i++) { if (!String.IsNullOrEmpty(mirrorData[i]) && !mirrorData[i].StartsWith("#")) { string[] fields = mirrorData[i].Split(new char[] { ';', '#' }); // Note, this will throw when it tries to parse the lines in the header. // Feel free to ignore those lines. try { int code = int.Parse(fields[0], NumberStyles.HexNumber); int mirror = int.Parse(fields[1], NumberStyles.HexNumber); mirrorDict.Add((char)code, (char)mirror); } catch { } } } // end of loop over each line. } string[] unicodeData = Storage4.ReadAllLines(@"Content\Xml\Unicode\UnicodeData.txt", StorageSource.TitleSpace); if (unicodeData != null) { for (int i = 0; i < unicodeData.Length; i++) { string[] fields = unicodeData[i].Split(';'); int code = 0; // If we throw trying to parse the code, just skip this glyph. try { code = int.Parse(fields[0], NumberStyles.HexNumber); } catch { continue; } UnicodeCharData data = new UnicodeCharData(); data.c = (char)code; data.name = fields[1]; data.type = fields[4]; data.decompositionMapping = fields[5]; data.mirrored = fields[9] == "Y"; // Ignore Arabic contextual forms for ligatures. This was causing too much breakage. if (data.name.Contains("LIGATURE") && data.name.Contains("ARABIC")) { continue; } if (data.decompositionMapping.StartsWith("<isolated>")) { // Parse may throw. If it does, just ignore this line. try { data.baseForm = (char)int.Parse(fields[5].Substring(fields[5].Length - 4), NumberStyles.HexNumber); DecompMappingData dm = null; decompMappingDict.TryGetValue(data.baseForm, out dm); if (dm == null) { dm = new DecompMappingData(); decompMappingDict.Add(data.baseForm, dm); dm.c = data.baseForm; } dm.isolated = data.c; } catch { } } else if (data.decompositionMapping.StartsWith("<initial>")) { // Parse may throw. If it does, just ignore this line. try { data.baseForm = (char)int.Parse(fields[5].Substring(fields[5].Length - 4), NumberStyles.HexNumber); DecompMappingData dm = null; decompMappingDict.TryGetValue(data.baseForm, out dm); if (dm == null) { dm = new DecompMappingData(); decompMappingDict.Add(data.baseForm, dm); dm.c = data.baseForm; } dm.initial = data.c; } catch { } } else if (data.decompositionMapping.StartsWith("<medial>")) { // Parse may throw. If it does, just ignore this line. try { data.baseForm = (char)int.Parse(fields[5].Substring(fields[5].Length - 4), NumberStyles.HexNumber); DecompMappingData dm = null; decompMappingDict.TryGetValue(data.baseForm, out dm); if (dm == null) { dm = new DecompMappingData(); decompMappingDict.Add(data.baseForm, dm); dm.c = data.baseForm; } dm.medial = data.c; } catch { } } else if (data.decompositionMapping.StartsWith("<final>")) { // Parse may throw. If it does, just ignore this line. try { data.baseForm = (char)int.Parse(fields[5].Substring(fields[5].Length - 4), NumberStyles.HexNumber); DecompMappingData dm = null; decompMappingDict.TryGetValue(data.baseForm, out dm); if (dm == null) { dm = new DecompMappingData(); decompMappingDict.Add(data.baseForm, dm); dm.c = data.baseForm; } dm.final = data.c; } catch { } } // Get ligature data from Decompostion Mapping field. Note that we're filtering // on only getting Arabic ligatures and ignoring other languages. This is because // it's too easy to find ligatures with no matching glyphs. if (data.name.Contains("ARABIC LIGATURE") && !string.IsNullOrEmpty(data.decompositionMapping)) { // HACK Finding too many missing characters so only look for the one required ligature. if (data.c != 0xfefb) { continue; } // Parse out the chars that combine to form this ligature. int index = data.decompositionMapping.LastIndexOf('>'); string[] args = data.decompositionMapping.Substring(index + 1).Trim().Split(' '); // Parse may throw. If it does, just ignore this ligature. try { char c0 = (char)int.Parse(args[0], NumberStyles.HexNumber); char[] chars = new char[args.Length - 1]; for (int c = 0; c < args.Length - 1; c++) { chars[c] = (char)int.Parse(args[c + 1], NumberStyles.HexNumber); } // Create or add to the ligature entry. Note that the entry // uses the first character of the pair for the key. LigatureData ld = null; ligatureDict.TryGetValue(c0, out ld); // Create new dictionary entry if needed. if (ld == null) { ld = new LigatureData(); ld.c = c0; ld.ligatures = new List <LigatureEntry>(); ligatureDict.Add(c0, ld); } // Add new entry. LigatureEntry le = new LigatureEntry(); le.chars = chars; le.joined = data.c; ld.ligatures.Add(le); } catch { } } if (data.mirrored) { mirrorDict.TryGetValue(data.c, out data.mirroredChar); } if (code >= 0 && code <= 0xFFFF) //UTF-16 BMP code points only { bool inRange = data.name.EndsWith(", First>"); if (inRange) // Add all characters within a specified range. { data.name.Replace(", First", String.Empty); // Remove range indicator from name . fields = unicodeData[++i].Split(';'); // Parse may throw. If it does, just ignore this range? // Not totally sure if this is the right thing to do... try { int endCharCode = int.Parse(fields[0], NumberStyles.HexNumber); if (!fields[1].EndsWith(", Last>")) { throw new Exception("Expected end-of-range indicator."); } for (int codeInRange = code; codeInRange <= endCharCode; codeInRange++) { charDict.Add((char)codeInRange, data); } } catch { } } else { charDict.Add((char)code, data); } } } // end of loop over each line. } // For ligatures, we need to be greedy and try to apply longer conversions // before shorter ones. So, sort all the ligatures in the dictionary by // the number of characters putting the longest first. foreach (LigatureData ld in ligatureDict.Values) { ld.ligatures.Sort(); } } // end of Init()
private Stream OpenTextureStream(string texFilename) { return(Storage4.TextureFileOpenRead(texFilename)); }
public override void Close(Stream stream) { Storage4.Close(stream); }