/** * create an area that formats a string. */ public static Area String(IFormattingContext context, String str) { Area result = null; float fontSize = context.Size; ArrayList list = null; int start = 0; if (str.Length == 1) { result = str[0] > '\x7f' ? GlyphFactory.GetGlyph(context, fontSize, str[0]) : new StringArea(context, str); } else { start = 0; for (int i = 0; i < str.Length; i++) { if (str[i] > '\x7f') { if (list == null) { list = new ArrayList(); } list.Add(new StringArea(context, str.Substring(start, i - start))); list.Add(GlyphFactory.GetGlyph(context, fontSize, str[i])); start = i + 1; } } if (list != null) { result = Horizontal((Area[])list.ToArray(typeof(Area))); } else { result = new StringArea(context, str); } } return(result); }
/** * find or calculate an area that will fill the requested cell * height. The returned area may be either a single glyph, or a * compound set of glyphs. * * @param pointSize the evaluated font size * @param desiredSize the desired stretch size (for either vertical or * horizontal stretchy glyphs. * @param c the character to find a glyph for. * @param lineThickness a value that get populated with the thickness of the * repated or stretched sections. */ public static Area GetStretchyGlyph(IFormattingContext context, float pointSize, char c, BoundingBox desiredSize, out float lineThickness) { GlyphFactory gf = Instance; Area result = null; lineThickness = 0; for (int i = 0; i < gf.maps.Length; i++) { if ((result = gf.maps[i].GetStretchyGlyph(context, pointSize, c, desiredSize, out lineThickness)) != null) { return(result); } } if (result == null) { Debug.WriteLine("no stretchy glyph found, returning standard glyph area"); result = GetGlyph(context, pointSize, c); } return(result); }
/** * create a new glyph area. */ public static Area GetGlyph(IFormattingContext ctx, float pointSize, char c) { GlyphFactory gf = Instance; Area result = null; Debug.WriteLine(String.Format("searching for a glyph for character 0x{0:x}", (uint)c)); for (int i = 0; i < gf.maps.Length; i++) { if ((result = gf.maps[i].GetGlyph(ctx, pointSize, c)) != null) { return(result); } } if (result == null) { Debug.WriteLine("no glyph found, returning default area"); result = new StringArea(ctx, "?"); } return(result); }
/** * format a radical */ public static Area Radical(IFormattingContext context, Area radicand, Area index) { const char RadicalGlyphIndex = '\x221a'; float fontSize = context.Size; BoundingBox radicandBox = radicand.BoundingBox; BoundingBox radicalBox; float minIndexWidth; float lineThickness; // these space numbers have no real meaning, the were just // chosen as a size that looks good. float leftSpace = 2 * context.OnePixel + radicandBox.Width * 0.01f; float rightSpace = 2 * context.OnePixel; float topMinSpace = context.OnePixel + radicandBox.VerticalExtent * 0.03f; // size to create glyph BoundingBox glyphBox = radicandBox; // add minimun stretch sizes to the box, sqrt is a vertical stretchy glyph glyphBox.Height += topMinSpace; // create a glyph for the radical char Area radical = GlyphFactory.GetStretchyGlyph(context, fontSize, RadicalGlyphIndex, glyphBox, out lineThickness); // line for the top part of the radical Area horizontalLine = HorizontalLine(lineThickness); radicalBox = radical.BoundingBox; // the glyph is almost never the exact size we request it, // we we need to adjust our vertical padding accoringly float topSpace = radicalBox.Height - radicandBox.Height - horizontalLine.BoundingBox.VerticalExtent; // pad the radicand with left and right spaces radicand = Horizontal(new Area[] { HorizontalSpace(leftSpace), radicand, HorizontalSpace(rightSpace) }); // make a new vertical array, with a line for the top of the radical spanning // the widtch, and the original radicand spaced slightly downward radicand = Vertical(new Area[] { radicand, VerticalSpace(topSpace, 0), horizontalLine }, 0); // get the minumum index width, this is needed as radical glyphs // are encoded with a negative left edge, this is where the right edge of // the index area would normally go. note, we better well have a // negative width, but just in case..... minIndexWidth = radical.LeftEdge < 0.0f ? -radical.LeftEdge : 0.0f; if (index == null) { // just make a space to padd the radical index = HorizontalSpace(minIndexWidth); } else { BoundingBox indexBox = index.BoundingBox; // need to pad the area if less than min width if (indexBox.Width < minIndexWidth) { index = Horizontal(new Area[] { HorizontalSpace(minIndexWidth - indexBox.Width), index }); } // shift the area up just above the radical hook index = Shift(GetRadicalShift(radical) + index.BoundingBox.Depth, index); } // hide the radical glyph from cursor selection radical = new NonSelectionArea(radical); // make a new horizontal area out of these three areas return(Horizontal(new Area[] { index, radical, radicand })); }