private void ParseGlyphRunProperties() { LayoutDependentGlyphRunProperties glyphRunProperties = null; Uri uri = FontUri; if (uri != null) { // Indices and UnicodeString cannot both be empty. if (String.IsNullOrEmpty(UnicodeString) && String.IsNullOrEmpty(Indices)) throw new ArgumentException(SR.Get(SRID.GlyphsUnicodeStringAndIndicesCannotBothBeEmpty)); glyphRunProperties = new LayoutDependentGlyphRunProperties(); if (!uri.IsAbsoluteUri) { uri = BindUriHelper.GetResolvedUri(BaseUriHelper.GetBaseUri(this), uri); } glyphRunProperties.glyphTypeface = new GlyphTypeface(uri, StyleSimulations); glyphRunProperties.unicodeString = UnicodeString; glyphRunProperties.sideways = IsSideways; glyphRunProperties.deviceFontName = DeviceFontName; // parse the Indices property List<ParsedGlyphData> parsedGlyphs; int glyphCount = ParseGlyphsProperty( glyphRunProperties.glyphTypeface, glyphRunProperties.unicodeString, glyphRunProperties.sideways, out parsedGlyphs, out glyphRunProperties.clusterMap); Debug.Assert(parsedGlyphs.Count == glyphCount); glyphRunProperties.glyphIndices = new ushort[glyphCount]; glyphRunProperties.advanceWidths = new double[glyphCount]; ParseCaretStops(glyphRunProperties); // Delay creating glyphOffsets array because in many common cases it will contain only zeroed entries. glyphRunProperties.glyphOffsets = null; int i = 0; glyphRunProperties.fontRenderingSize = FontRenderingEmSize; glyphRunProperties.bidiLevel = BidiLevel; double fromEmToMil = glyphRunProperties.fontRenderingSize / EmMultiplier; foreach (ParsedGlyphData parsedGlyphData in parsedGlyphs) { glyphRunProperties.glyphIndices[i] = parsedGlyphData.glyphIndex; // convert advances and offsets from integers in em space to doubles coordinates in MIL space glyphRunProperties.advanceWidths[i] = parsedGlyphData.advanceWidth * fromEmToMil; if (parsedGlyphData.offsetX != 0 || parsedGlyphData.offsetY != 0) { // Lazily create glyph offset array. Previous entries will be correctly set to zero // by the default Point ctor. if (glyphRunProperties.glyphOffsets == null) glyphRunProperties.glyphOffsets = new Point[glyphCount]; glyphRunProperties.glyphOffsets[i].X = parsedGlyphData.offsetX * fromEmToMil; glyphRunProperties.glyphOffsets[i].Y = parsedGlyphData.offsetY * fromEmToMil; } ++i; } } _glyphRunProperties = glyphRunProperties; }
private void ParseGlyphRunProperties() { LayoutDependentGlyphRunProperties glyphRunProperties = null; Uri uri = FontUri; if (uri != null) { // Indices and UnicodeString cannot both be empty. if (String.IsNullOrEmpty(UnicodeString) && String.IsNullOrEmpty(Indices)) { throw new ArgumentException(SR.Get(SRID.GlyphsUnicodeStringAndIndicesCannotBothBeEmpty)); } glyphRunProperties = new LayoutDependentGlyphRunProperties(GetDpi().PixelsPerDip); if (!uri.IsAbsoluteUri) { uri = BindUriHelper.GetResolvedUri(BaseUriHelper.GetBaseUri(this), uri); } glyphRunProperties.glyphTypeface = new GlyphTypeface(uri, StyleSimulations); glyphRunProperties.unicodeString = UnicodeString; glyphRunProperties.sideways = IsSideways; glyphRunProperties.deviceFontName = DeviceFontName; // parse the Indices property List <ParsedGlyphData> parsedGlyphs; int glyphCount = ParseGlyphsProperty( glyphRunProperties.glyphTypeface, glyphRunProperties.unicodeString, glyphRunProperties.sideways, out parsedGlyphs, out glyphRunProperties.clusterMap); Debug.Assert(parsedGlyphs.Count == glyphCount); glyphRunProperties.glyphIndices = new ushort[glyphCount]; glyphRunProperties.advanceWidths = new double[glyphCount]; ParseCaretStops(glyphRunProperties); // Delay creating glyphOffsets array because in many common cases it will contain only zeroed entries. glyphRunProperties.glyphOffsets = null; int i = 0; glyphRunProperties.fontRenderingSize = FontRenderingEmSize; glyphRunProperties.bidiLevel = BidiLevel; double fromEmToMil = glyphRunProperties.fontRenderingSize / EmMultiplier; foreach (ParsedGlyphData parsedGlyphData in parsedGlyphs) { glyphRunProperties.glyphIndices[i] = parsedGlyphData.glyphIndex; // convert advances and offsets from integers in em space to doubles coordinates in MIL space glyphRunProperties.advanceWidths[i] = parsedGlyphData.advanceWidth * fromEmToMil; if (parsedGlyphData.offsetX != 0 || parsedGlyphData.offsetY != 0) { // Lazily create glyph offset array. Previous entries will be correctly set to zero // by the default Point ctor. if (glyphRunProperties.glyphOffsets == null) { glyphRunProperties.glyphOffsets = new Point[glyphCount]; } glyphRunProperties.glyphOffsets[i].X = parsedGlyphData.offsetX * fromEmToMil; glyphRunProperties.glyphOffsets[i].Y = parsedGlyphData.offsetY * fromEmToMil; } ++i; } } _glyphRunProperties = glyphRunProperties; }
private void ParseCaretStops(LayoutDependentGlyphRunProperties glyphRunProperties) { string caretStopsString = CaretStops; if (String.IsNullOrEmpty(caretStopsString)) { glyphRunProperties.caretStops = null; return; } // Caret stop count should be equal to the number of UTF16 code points in the glyph run plus one. // Logic below is similar to GlyphRun.CodepointCount property. int caretStopCount; if (!String.IsNullOrEmpty(glyphRunProperties.unicodeString)) caretStopCount = glyphRunProperties.unicodeString.Length + 1; else { if (glyphRunProperties.clusterMap != null && glyphRunProperties.clusterMap.Length != 0) caretStopCount = glyphRunProperties.clusterMap.Length + 1; else { Debug.Assert(glyphRunProperties.glyphIndices != null); caretStopCount = glyphRunProperties.glyphIndices.Length + 1; } } bool[] caretStops = new bool[caretStopCount]; int i = 0; foreach (char c in caretStopsString) { if (Char.IsWhiteSpace(c)) continue; int nibble; if ('0' <= c && c <= '9') nibble = c - '0'; else if ('a' <= c && c <= 'f') nibble = c - 'a' + 10; else if ('A' <= c && c <= 'F') nibble = c - 'A' + 10; else throw new ArgumentException(SR.Get(SRID.GlyphsCaretStopsContainsHexDigits), "CaretStops"); Debug.Assert(0 <= nibble && nibble <= 15); if ((nibble & 8) != 0) { if (i >= caretStops.Length) throw new ArgumentException(SR.Get(SRID.GlyphsCaretStopsLengthCorrespondsToUnicodeString), "CaretStops"); caretStops[i] = true; } ++i; if ((nibble & 4) != 0) { if (i >= caretStops.Length) throw new ArgumentException(SR.Get(SRID.GlyphsCaretStopsLengthCorrespondsToUnicodeString), "CaretStops"); caretStops[i] = true; } ++i; if ((nibble & 2) != 0) { if (i >= caretStops.Length) throw new ArgumentException(SR.Get(SRID.GlyphsCaretStopsLengthCorrespondsToUnicodeString), "CaretStops"); caretStops[i] = true; } ++i; if ((nibble & 1) != 0) { if (i >= caretStops.Length) throw new ArgumentException(SR.Get(SRID.GlyphsCaretStopsLengthCorrespondsToUnicodeString), "CaretStops"); caretStops[i] = true; } ++i; } // If the number of entries in the caret stop specification string is less than the number of code points, // set the remaining caret stop values to true. while (i < caretStops.Length) { caretStops[i++] = true; } glyphRunProperties.caretStops = caretStops; }
private void ParseCaretStops(LayoutDependentGlyphRunProperties glyphRunProperties) { string caretStopsString = CaretStops; if (String.IsNullOrEmpty(caretStopsString)) { glyphRunProperties.caretStops = null; return; } // Caret stop count should be equal to the number of UTF16 code points in the glyph run plus one. // Logic below is similar to GlyphRun.CodepointCount property. int caretStopCount; if (!String.IsNullOrEmpty(glyphRunProperties.unicodeString)) { caretStopCount = glyphRunProperties.unicodeString.Length + 1; } else { if (glyphRunProperties.clusterMap != null && glyphRunProperties.clusterMap.Length != 0) { caretStopCount = glyphRunProperties.clusterMap.Length + 1; } else { Debug.Assert(glyphRunProperties.glyphIndices != null); caretStopCount = glyphRunProperties.glyphIndices.Length + 1; } } bool[] caretStops = new bool[caretStopCount]; int i = 0; foreach (char c in caretStopsString) { if (Char.IsWhiteSpace(c)) { continue; } int nibble; if ('0' <= c && c <= '9') { nibble = c - '0'; } else if ('a' <= c && c <= 'f') { nibble = c - 'a' + 10; } else if ('A' <= c && c <= 'F') { nibble = c - 'A' + 10; } else { throw new ArgumentException(SR.Get(SRID.GlyphsCaretStopsContainsHexDigits), "CaretStops"); } Debug.Assert(0 <= nibble && nibble <= 15); if ((nibble & 8) != 0) { if (i >= caretStops.Length) { throw new ArgumentException(SR.Get(SRID.GlyphsCaretStopsLengthCorrespondsToUnicodeString), "CaretStops"); } caretStops[i] = true; } ++i; if ((nibble & 4) != 0) { if (i >= caretStops.Length) { throw new ArgumentException(SR.Get(SRID.GlyphsCaretStopsLengthCorrespondsToUnicodeString), "CaretStops"); } caretStops[i] = true; } ++i; if ((nibble & 2) != 0) { if (i >= caretStops.Length) { throw new ArgumentException(SR.Get(SRID.GlyphsCaretStopsLengthCorrespondsToUnicodeString), "CaretStops"); } caretStops[i] = true; } ++i; if ((nibble & 1) != 0) { if (i >= caretStops.Length) { throw new ArgumentException(SR.Get(SRID.GlyphsCaretStopsLengthCorrespondsToUnicodeString), "CaretStops"); } caretStops[i] = true; } ++i; } // If the number of entries in the caret stop specification string is less than the number of code points, // set the remaining caret stop values to true. while (i < caretStops.Length) { caretStops[i++] = true; } glyphRunProperties.caretStops = caretStops; }