Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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));
        }
Exemplo n.º 5
0
        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));
        }
Exemplo n.º 6
0
        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);
                }
            }));
        }