public static (string Hex, string FontIcon, string Path, string Symbol) GetDevValues( Character c, FontVariant v, CanvasTextLayoutAnalysis a, CanvasTypography t, bool isXaml) { if (v == FontFinder.DefaultFont.DefaultVariant) { return(string.Empty, string.Empty, string.Empty, string.Empty); } NativeInterop interop = Utils.GetInterop(); string h, f, p, s = null; bool hasSymbol = FontFinder.IsMDL2(v) && Enum.IsDefined(typeof(Symbol), (int)c.UnicodeIndex); // Add back in future build //string pathData; //using (var geom = ExportManager.CreateGeometry(ResourceHelper.AppSettings.GridSize, v, c, a, t)) //{ // pathData = interop.GetPathData(geom).Path; //} string pathIconData; using (var geom = ExportManager.CreateGeometry(20, v, c, a, t)) { pathIconData = interop.GetPathData(geom).Path; } var hex = c.UnicodeIndex.ToString("x4").ToUpper(); if (isXaml) { h = $"&#x{hex};"; f = $@"<FontIcon FontFamily=""{v.XamlFontSource}"" Glyph=""&#x{hex};"" />"; p = $"<PathIcon Data=\"{pathIconData}\" VerticalAlignment=\"Center\" HorizontalAlignment=\"Center\" />"; if (hasSymbol) { s = $@"<SymbolIcon Symbol=""{(Symbol)c.UnicodeIndex}"" />"; } } else { h = c.UnicodeIndex > 0xFFFF ? $"\\U{c.UnicodeIndex:x8}".ToUpper() : $"\\u{hex}"; f = $"new FontIcon {{ FontFamily = new Windows.UI.Xaml.Media.FontFamily(\"{v.XamlFontSource}\") , Glyph = \"\\u{hex}\" }};"; p = $"new PathIcon {{ Data = (Windows.UI.Xaml.Media.Geometry)Windows.UI.Xaml.Markup.XamlBindingHelper.ConvertValue(typeof(Geometry), \"{pathIconData}\"), HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }};"; if (hasSymbol) { s = $"new SymbolIcon {{ Symbol = Symbol.{(Symbol)c.UnicodeIndex} }};"; } } return(h, f, p, s); }
public static (string Hex, string FontIcon, string Path, string Symbol) GetDevValues( Character c, FontVariant v, CanvasTextLayoutAnalysis a, CanvasTypography t, bool isXaml) { if (v == FontFinder.DefaultFont.DefaultVariant) { return(string.Empty, string.Empty, string.Empty, string.Empty); } Interop interop = SimpleIoc.Default.GetInstance <Interop>(); string h, f, p, s = null; bool hasSymbol = FontFinder.IsMDL2(v) && Enum.IsDefined(typeof(Symbol), c.UnicodeIndex); string pathData; using (var geom = ExportManager.CreateGeometry(ResourceHelper.AppSettings.GridSize, v, c, a, t)) { pathData = interop.GetPathData(geom).Path; } var hex = c.UnicodeIndex.ToString("x4").ToUpper(); if (isXaml) { h = $"&#x{hex};"; f = $@"<FontIcon FontFamily=""{v.XamlFontSource}"" Glyph=""&#x{hex};"" />"; p = $"<Path Data=\"{pathData}\" Fill=\"{{ThemeResource SystemControlForegroundBaseHighBrush}}\" Stretch=\"Uniform\" />"; if (hasSymbol) { s = $@"<SymbolIcon Symbol=""{(Symbol)c.UnicodeIndex}"" />"; } } else { h = $"\\u{hex}"; f = $"new FontIcon {{ FontFamily = new Windows.UI.Xaml.Media.FontFamily(\"{v.XamlFontSource}\") , Glyph = \"\\u{hex}\" }};"; p = $"new Windows.UI.Xaml.Shapes.Path {{ Data = (Windows.UI.Xaml.Media.Geometry)Windows.UI.Xaml.Markup.XamlBindingHelper.ConvertValue(typeof(Geometry), \"{pathData}\"), Fill = new Windows.UI.Xaml.Media.SolidColorBrush(Windows.UI.Colors.Black), Stretch = Windows.UI.Xaml.Media.Stretch.Uniform }};"; if (hasSymbol) { s = $"new SymbolIcon {{ Symbol = Symbol.{(Symbol)c.UnicodeIndex} }};"; } } return(h, f, p, s); }
public string GetCharacterDescription(int unicodeIndex, FontVariant variant) { if (FontFinder.IsMDL2(variant)) { return(_connection.Get <MDL2Glyph>(g => g.UnicodeIndex == unicodeIndex)?.Description); } if (IsFontAwesome(variant)) { return(_connection.Get <FontAwesomeGlyph>(g => g.UnicodeIndex == unicodeIndex)?.Description); } if (variant.FontFace.IsSymbolFont) { return(null); } return(_connection.Get <UnicodeGlyphData>(u => u.UnicodeIndex == unicodeIndex)?.Description); }
public Task <IReadOnlyList <IGlyphData> > SearchAsync(string query, FontVariant variant) { if (string.IsNullOrWhiteSpace(query)) { return(Task.FromResult(GlyphService.EMPTY_SEARCH)); } /* MDL2 has special dataset */ if (FontFinder.IsMDL2(variant)) { return(SearchMDL2Async(query, variant)); } /* FontAwesome has special dataset */ if (IsFontAwesome(variant)) { return(SearchFontAwesomeAsync(query, variant)); } /* Generic Unicode Search */ return(SearchUnicodeAsync(query, variant)); }
public Task <IReadOnlyList <IGlyphData> > SearchAsync(string query, FontVariant variant) { if (string.IsNullOrWhiteSpace(query)) { return(Task.FromResult(GlyphService.EMPTY_SEARCH)); } /* MDL2 has special dataset */ if (FontFinder.IsMDL2(variant)) { return(SearchMDL2Async(query, variant)); } foreach (SearchTarget target in SearchTarget.KnownTargets) { if (target.IsTarget(variant)) { return(InternalSearchAsync(target.SearchTable, target.TargetType.Name, query, variant)); } } /* Generic Unicode Search */ return(SearchUnicodeAsync(query, variant)); }
public string GetCharacterDescription(int unicodeIndex, FontVariant variant) { string desc = null; // MDL2 has it's own special logic if (FontFinder.IsMDL2(variant)) { desc = _connection.Get <MDL2Glyph>(g => g.UnicodeIndex == unicodeIndex)?.Description; if (string.IsNullOrWhiteSpace(desc) && Enum.IsDefined(typeof(Symbol), unicodeIndex)) { return(((Symbol)unicodeIndex).ToString().Humanize(LetterCasing.Title)); } return(desc); } // Otherwise check if we have a search table for this font foreach (var target in SearchTarget.KnownTargets) { if (target.IsTarget(variant)) { var map = _connection.GetMapping(target.TargetType); var items = _connection.Query(map, $"SELECT * FROM {target.SearchTable} WHERE Ix = ? LIMIT 1", unicodeIndex); desc = (items.FirstOrDefault() as GlyphDescription)?.Description; break; } } // Otherwise get a fallback value if (string.IsNullOrEmpty(desc)) { desc = _connection.Get <UnicodeGlyphData>(u => u.UnicodeIndex == unicodeIndex)?.Description; } return(desc); }
private Task <IReadOnlyList <IGlyphData> > InternalSearchAsync(string ftsTable, string table, string query, FontVariant variant) { return(Task.Run <IReadOnlyList <IGlyphData> >(() => { /* * Step 1: Perform single-result Hex Search if hex * Step 2: Perform FTS search if not hex or ambiguous * Step 3: Perform LIKE search if still space for results */ // 1. Decide if hex or FTS4 search // 1.1. If hex, search the main table (UnicodeIndex column is indexed) GlyphDescription hexResult = null; bool ambiguous = !variant.FontFace.IsSymbolFont && IsAmbiguousQuery(query); if (Utils.TryParseHexString(query, out int hex)) { // 1.2. To be more efficient, first check if the font actually contains the UnicodeIndex. // If it does then we ask the database, otherwise we can return without query. foreach (var range in variant.UnicodeRanges) { if (hex >= range.Item1 && hex <= range.Item2) { string hexsql = $"SELECT * FROM {table} WHERE UnicodeIndex == {hex} LIMIT 1"; var hexresults = _connection.Query <GlyphDescription>(hexsql, query)?.Cast <IGlyphData>()?.ToList(); if (hexresults == null || hexresults.Count == 0) { var label = hex.ToString("X"); hexresults = new List <IGlyphData>() { new GlyphDescription { UnicodeIndex = hex, UnicodeHex = label, Description = label } }; } // 1.3. If the search is ambiguous we should still search for description matches, // otherwise we can return right now if (!ambiguous) { return hexresults; } else { hexResult = hexresults.Cast <GlyphDescription>().FirstOrDefault(); break; } } } // 1.4. If the search is ambiguous we should still search for description matches, // otherwise we can return right now with no hex results // If we are a generic symbol font, that's all folks. Time to leave. if (!ambiguous) { return GlyphService.EMPTY_SEARCH; } } // 1.5. If we are a generic symbol font, we don't match by character name so time to go home. if (!FontFinder.IsMDL2(variant) && !IsFontAwesome(variant) && variant.FontFace.IsSymbolFont) { return GlyphService.EMPTY_SEARCH; } // 2. If we're performing SQL, create the base query filter StringBuilder sb = new StringBuilder(); bool next = false; foreach ((int, int)range in variant.UnicodeRanges) { if (next) { sb.AppendFormat(" OR UnicodeIndex BETWEEN {0} AND {1}", range.Item1, range.Item2); } else { next = true; sb.AppendFormat("WHERE (UnicodeIndex BETWEEN {0} AND {1}", range.Item1, range.Item2); } } sb.Append(")"); // 2.1. A helper method to inject the hex result for ambiguous searches List <IGlyphData> InsertHex(List <IGlyphData> list) { if (hexResult != null) { list.Insert(0, hexResult); } return list; } // 3. Otherwise, perform a multi-step text search. First perform an FTS4 search string sql = $"SELECT * FROM {ftsTable} {sb.ToString()} AND Description MATCH '{query}' LIMIT {SEARCH_LIMIT}"; var results = _connection.Query <GlyphDescription>(sql, query)?.Cast <IGlyphData>()?.ToList(); // 4. If we have SEARCH_LIMIT matches, we don't need to perform a partial search and can go home early if (results != null && results.Count == SEARCH_LIMIT) { return InsertHex(results); } // 5. Perform a partial search on non-FTS table. Only search for what we need. // This means limit the amount of results, and exclude anything we've already matched. int limit = results == null ? SEARCH_LIMIT : SEARCH_LIMIT - results.Count; if (limit != SEARCH_LIMIT) { // 5.1. We need to exclude anything already found above sb.AppendFormat("AND UnicodeIndex NOT IN ({0})", string.Join(", ", results.Select(r => r.UnicodeIndex))); } // 6. Execute on the non FTS tables string sql2 = $"SELECT * FROM {table} {sb.ToString()} AND Description LIKE '%{query}%' LIMIT {limit}"; var results2 = _connection.Query <GlyphDescription>(sql2, query)?.Cast <IGlyphData>()?.ToList(); if (results != null) { results.AddRange(results2); return InsertHex(results); } else { return InsertHex(results2); } })); }