/** * set the attributes, but do not actually create a glyph * area. * @param fontHandle a handle to a native font resource * @param charIndex the index in the font of the desired glyph * @param stretchyType if this glyph is a repeated section in a * stretchy glyph, shrink the reported metrics by one, so * we get a nice overlap. */ public GlyphAttributes(IFormattingContext context, IFontHandle fontHandle, short charIndex, int fudge) { Index = charIndex; glyphArea = null; float tmp; if (charIndex >= 0) { context.MeasureGlyph(fontHandle, (ushort)charIndex, out Box, out Left, out Right); if (fudge == FudgeWidth) { Box.Width -= 2 * fudgeFactor; } else if (fudge == FudgeHeight) { if ((tmp = Box.Height - fudgeFactor) >= 0.0f) { Box.Height = tmp; } if ((tmp = Box.Depth - fudgeFactor) >= 0.0f) { Box.Depth = tmp; } } } else { Box = new BoundingBox(); Left = 0; Right = 0; } }
private static Row[] CreateRows(IFormattingContext ctx, MathMLTableCellElement[][] cells, BoundingBox[][] minCellSizes, Length[] rowSpacing, Length frameSpacing) { int i = 0; int space = 0; // new row array: row count + spacing rows + border spacing // = (row count) + (row count - 1) + 2 // = (row count) + (row count) + 1 Row[] rows = new Row[minCellSizes.Length + minCellSizes.Length + 1]; // frame spacing rows[i++] = new Row(ctx.Evaluate(frameSpacing)); for (int j = 0; j < minCellSizes.Length; j++) { // cell row rows[i++] = new Row(cells[j], minCellSizes[j]); // spacing row if (j < minCellSizes.Length - 1) { rows[i++] = new Row(ctx.Evaluate(rowSpacing[space++])); } } // final frame spacing rows[i++] = new Row(ctx.Evaluate(frameSpacing)); // sanity check Debug.Assert(i == rows.Length, "error, row count and processed row count do not match"); return(rows); }
/** * set the attributes, but do not actually create a glyph * area. * @param fontHandle a handle to a native font resource * @param charIndex the index in the font of the desired glyph * @param stretchyType if this glyph is a repeated section in a * stretchy glyph, shrink the reported metrics by one, so * we get a nice overlap. */ public GlyphAttributes(IFormattingContext context, IFontHandle fontHandle, short charIndex, int fudge) { Index = charIndex; glyphArea = null; float tmp; if(charIndex >= 0) { context.MeasureGlyph(fontHandle, (ushort)charIndex, out Box, out Left, out Right); if(fudge == FudgeWidth) { Box.Width -= 2 * fudgeFactor; } else if(fudge == FudgeHeight) { if((tmp = Box.Height - fudgeFactor) >= 0.0f) Box.Height = tmp; if((tmp = Box.Depth - fudgeFactor) >= 0.0f) Box.Depth = tmp; } } else { Box = new BoundingBox(); Left = 0; Right = 0; } }
/** * create a set of attributes. * this calculates all of the glyph metrics from the graphic device. */ public StretchyGlyphAttributes(IFormattingContext context, IFontHandle fontHandle, ref StretchyGlyphIndices indices) { orientation = indices.Orientation; if(indices.SimpleIndices != null) { simpleGlyphs = new GlyphAttributes[indices.SimpleIndices.Length]; for(int i = 0; i < simpleGlyphs.Length; i++) { simpleGlyphs[i] = new GlyphAttributes(context, fontHandle, indices.SimpleIndices[i], GlyphAttributes.FudgeNone); } } else { simpleGlyphs = null; } if(indices.CompoundIndices != null) { compoundGlyphs = new GlyphAttributes[indices.CompoundIndices.Length]; for(int i = 0; i < compoundGlyphs.Length; i++) { // TODO deal with horizontal glyphs compoundGlyphs[i] = new GlyphAttributes(context, fontHandle, indices.CompoundIndices[i], i == StretchyGlyphIndices.Filler ? GlyphAttributes.FudgeHeight : GlyphAttributes.FudgeNone); } } else { compoundGlyphs = null; } }
/// <summary> /// Get the minimum formatted area size for the given element using the /// state of the given formatting context. /// /// Currently this just formats the element using the this as the formatter, /// in the future, this will be optimized so that a visitor only calculates /// the min size instead of creating an entire sub tree of areas. /// </summary> public BoundingBox MeasureElement(IFormattingContext ctx, MathMLElement e) { Debug.Assert(ctx.cacheArea == false); if (e != null) { Area a = Area.GetArea(e); if (a != null) { return(a.BoundingBox); } if (cache.Contains(e)) { return((BoundingBox)cache[e]); } else { if (e is MathMLTableElement) { Debug.WriteLine("table element"); } BoundingBox box = (BoundingBox)e.Accept(this, ctx); cache.Add(e, box); return(box); } } else { return(BoundingBox.New()); } }
/** * create a set of attributes. * this calculates all of the glyph metrics from the graphic device. */ public StretchyGlyphAttributes(IFormattingContext context, IFontHandle fontHandle, ref StretchyGlyphIndices indices) { orientation = indices.Orientation; if (indices.SimpleIndices != null) { simpleGlyphs = new GlyphAttributes[indices.SimpleIndices.Length]; for (int i = 0; i < simpleGlyphs.Length; i++) { simpleGlyphs[i] = new GlyphAttributes(context, fontHandle, indices.SimpleIndices[i], GlyphAttributes.FudgeNone); } } else { simpleGlyphs = null; } if (indices.CompoundIndices != null) { compoundGlyphs = new GlyphAttributes[indices.CompoundIndices.Length]; for (int i = 0; i < compoundGlyphs.Length; i++) { // TODO deal with horizontal glyphs compoundGlyphs[i] = new GlyphAttributes(context, fontHandle, indices.CompoundIndices[i], i == StretchyGlyphIndices.Filler ? GlyphAttributes.FudgeHeight : GlyphAttributes.FudgeNone); } } else { compoundGlyphs = null; } }
/** * get a font based on the font type given in the variant, * and the size given in height. If the size can not be * evaluated to a valid size, the default font size is used. * the fontName override anything in the context if it is given. */ public IFontHandle GetFont(IFormattingContext context, string fontName, string altFontName) { // font to be returned IFontHandle font = null; // find the attributes from the static array FontAttributes attr = fontAttributes[(int)context.MathVariant]; float height = context.Size; // no italic if we are using the font name, otherwise use the // value from the mathvariant attribute bool italic = fontName.Length > 0 ? false : attr.Italic; // use default value if we are using the font specified by a name, // otherwise use the one from the attributes from mathvariant int weight = fontName.Length > 0 ? DefaultFontWeight : attr.Weight; // use either the fontName stirng if we have one, or the one // from the mathvariant attribute string name = fontName.Length > 0 ? fontName : attr.Name; font = FindFont(height, italic, weight, name); if (font == null) { font = CreateFont(((WinFormattingContext)context)._graphics, height, italic, weight, name); fonts.Add(new WeakReference(font)); } return(font); }
public static Area Glyph(IFormattingContext context, String fontName, String altFontName, ushort index) { IFontHandle font = context.GetFont(fontName, altFontName); return(new GlyphArea(context, font, index)); }
/// <summary> /// Get the minimum formatted area size for the given element using the /// state of the given formatting context. /// /// Currently this just formats the element using the this as the formatter, /// in the future, this will be optimized so that a visitor only calculates /// the min size instead of creating an entire sub tree of areas. /// </summary> public BoundingBox MeasureElement(IFormattingContext ctx, MathMLElement e) { Debug.Assert(ctx.cacheArea == false); if(e != null) { Area a = Area.GetArea(e); if(a != null) return a.BoundingBox; if(cache.Contains(e)) { return (BoundingBox)cache[e]; } else { if(e is MathMLTableElement) { Debug.WriteLine("table element"); } BoundingBox box = (BoundingBox)e.Accept(this, ctx); cache.Add(e, box); return box; } } else { return BoundingBox.New(); } }
/** * construct a new TableColumn object */ public Column(IFormattingContext ctx, Length columnWidth, float evaluatedWidth, bool spacing) { Spacing = spacing; if (spacing) { if (columnWidth.Type == LengthType.Percentage) { MinimumWidth = 0; } else if (columnWidth.Fixed) { MinimumWidth = ctx.Evaluate(columnWidth); } else { // this is bad throw new Exception("space columns must be either fixed or scaled widths"); } } else { MinimumWidth = evaluatedWidth; } if (columnWidth.Type == LengthType.Auto) { Type = ColumnType.Auto; ScaleWidth = 0; FixedWidth = 0; Width = MinimumWidth; } else if (columnWidth.Type == LengthType.Fit) { Type = ColumnType.Fit; ScaleWidth = 0; FixedWidth = 0; Width = MinimumWidth; } else if (columnWidth.Type == LengthType.Percentage) { Type = ColumnType.Scale; ScaleWidth = columnWidth.Value / 100.0f; FixedWidth = 0; Width = MinimumWidth; } else if (columnWidth.Fixed) { Type = ColumnType.Fixed; ScaleWidth = 0; FixedWidth = MinimumWidth; Width = MinimumWidth; } else { // this is bad throw new Exception(columnWidth.ToString() + " is not a valid length type for a table"); } }
/** * calculate the default amout the script the baseline of the * script rows. this ignores (for now anyway) the min shift values * specified in the DOM */ private static void CalculateScriptShift(IFormattingContext context, BoundingBox baseBox, BoundingBox subBox, Length subMinSize, BoundingBox superBox, Length superMinSize, out float subShift, out float superShift) { CalculateScriptShift(context, baseBox, subBox, superBox, out subShift, out superShift); }
public BoundingBox[][] MeasureElements(IFormattingContext ctx, MathMLElement[][] elements) { BoundingBox[][] boxes = new BoundingBox[elements.Length][]; for (int i = 0; i < elements.Length; i++) { boxes[i] = MeasureElements(ctx, elements[i]); } return(boxes); }
object MathML.MathMLVisitor.Visit(MathMLPresentationToken e, object args) { Area area = null; // make an updated context IFormattingContext context = ((IFormattingContext)args).Clone(); XmlNode node = null; MathMLElement element = null; MathMLNodeList contents = e.Contents; // update the font size, pres-tokens can specify font size context.Size = context.Evaluate(e.MathSize); MathVariant variant = e.MathVariant; if (variant != MathVariant.Unknown) { context.MathVariant = variant; } if (contents.Count == 1) // create a single string area { if ((node = e.FirstChild) != null && node.NodeType == XmlNodeType.Text) { area = AreaFactory.String(context, node.Value); } else if ((element = e.FirstChild as MathMLElement) != null) { // sets area to a new glyph area area = (Area)element.Accept(formatter, context); } else { // TODO this is bad, need error handler } } else // create a sequence of areas { Area[] areas = new Area[contents.Count]; int i = 0; foreach (XmlNode n in contents) { if (n.NodeType == XmlNodeType.Text) { area = AreaFactory.String(context, n.Value); } else if ((element = n as MathMLElement) != null) { area = (Area)element.Accept(formatter, context); } areas[i++] = area; } area = AreaFactory.Horizontal(areas); } return(area.BoundingBox); }
public override AreaRegion GetRegion(IFormattingContext context, float x, float y, Area area, int index) { AreaRegion region = child.GetRegion (context, x, y, area, index); if(region != null && region.Element == null) { region.Element = element; } return region; }
/** * create a font with the given font size. return the index of the new * font, or -1 if we failed to create the font */ private int CreateFont(IFormattingContext context, float fontSize) { fontSize = (fontSize * scaleFactor); FontInstance[] tmp = fontInstances; fontInstances = new FontInstance[fontInstances.Length + 1]; tmp.CopyTo(fontInstances, 0); fontInstances[fontInstances.Length - 1] = new FontInstance(context, fontName, fontSize, stretchyGlyphIndices); return(fontInstances.Length - 1); }
public Area GetArea(IFormattingContext context, IFontHandle fontHandle, char c) { Area result = null; ushort glyphIndex = (ushort)(c + offset); if (glyphIndex >= first && glyphIndex <= last) { result = new GlyphArea(context, fontHandle, glyphIndex); } return result; }
public override AreaRegion GetRegion(IFormattingContext context, float x, float y, Area area, int index) { AreaRegion region = child.GetRegion(context, x, y, area, index); if (region != null && region.Element == null) { region.Element = element; } return(region); }
public Area GetArea(IFormattingContext context, IFontHandle fontHandle, char c) { Area result = null; ushort glyphIndex = (ushort)(c + offset); if (glyphIndex >= first && glyphIndex <= last) { result = new GlyphArea(context, fontHandle, glyphIndex); } return(result); }
public virtual AreaRegion GetRegion(IFormattingContext context, float x, float y, Area area, int index) { if (index == 0 && area == this) { return(new AreaRegion(this, x + LeftEdge, y)); } else { return(null); } }
public override AreaRegion GetRegion(IFormattingContext context, float x, float y, Area area, int index) { if (area == source) { return(new AreaRegion(this, x, y)); } else { return(child.GetRegion(context, x, y, area, index)); } }
public override AreaRegion GetRegion(IFormattingContext context, float x, float y, MathMLElement element, int index) { if (element == this.element) { return(new AreaRegion(this, element, x + cellShift.X, y + cellShift.Y)); } else { return(child.GetRegion(context, x + areaShift.X, y + areaShift.Y, element, index)); } }
public FontInstance(IFormattingContext context, string fontName, float pointSize, StretchyGlyphIndices[] glyphIndices) { cachedAreas = null; PointSize = pointSize; FontHandle = context.CreateFont(pointSize, false, 500, fontName); stretchyAttributes = new StretchyGlyphAttributes[glyphIndices.Length]; for (int i = 0; i < stretchyAttributes.Length; i++) { stretchyAttributes[i] = new StretchyGlyphAttributes( context, FontHandle, ref glyphIndices[i]); } }
public FontInstance(IFormattingContext context, string fontName, float pointSize, StretchyGlyphIndices[] glyphIndices) { cachedAreas = null; PointSize = pointSize; FontHandle = context.CreateFont(pointSize, false, 500, fontName); stretchyAttributes = new StretchyGlyphAttributes[glyphIndices.Length]; for(int i = 0; i < stretchyAttributes.Length; i++) { stretchyAttributes[i] = new StretchyGlyphAttributes( context, FontHandle, ref glyphIndices[i]); } }
public override AreaRegion GetEditRegion(IFormattingContext context, float x, float y, int index) { foreach (Area a in content) { AreaRegion r = a.GetEditRegion(context, x, y, index); if (r != null) { return(r); } } return(null); }
public override AreaRegion GetRegion(IFormattingContext context, float x, float y, MathMLElement element, int index) { foreach (Area a in content) { AreaRegion r = a.GetRegion(context, x, y, element, index); if (r != null) { return(r); } x += a.BoundingBox.HorizontalExtent; } return(null); }
/** * Create a fraction area. * This is an area that consists of 2 areas vertically separated by a line. * this notion natuarally falls into the conecpt of a vertical array area, * an area, a line, and the second area. */ public static Area Fraction(IFormattingContext ctx, Area numerator, Area denominator, float lineThickness) { Area space = new VerticalSpaceArea(ctx.OnePixel, ctx.OnePixel); Area line = HorizontalLine(ctx.OnePixel); numerator = HorizontalCenter(numerator); denominator = HorizontalCenter(denominator); Area[] areas = { denominator, space, line, space, numerator }; return(Shift(ctx.Axis, new VerticalArea(areas, 2))); }
public override AreaRegion GetEditRegion(IFormattingContext context, float x, float y, int index) { // measure horizontal position of char: BoundingBox horz = BoundingBox.New(); float left, right; for (int i = 0; i < index && i < content.Length; i++) { BoundingBox tmp = BoundingBox.New(); context.MeasureGlyph(font, content[i], out tmp, out left, out right); horz.Append(tmp); } return(new AreaRegion(this, x + horz.Width, y)); }
/** * find an index to a font that mathces the given font cell height, * if no font is availible, one is created with this height. */ private int GetFontIndex(IFormattingContext context, float fontSize) { fontSize = (fontSize * scaleFactor); for (int i = 0; i < fontInstances.Length; i++) { if (fontInstances[i].PointSize == fontSize) { return(i); } } // no font found, so try to create one. return(CreateFont(context, fontSize)); }
public BoundingBox[] MeasureElements(IFormattingContext ctx, MathMLElement[] elements) { BoundingBox[] boxes = new BoundingBox[elements.Length]; for (int i = 0; i < elements.Length; i++) { if (elements[i] != null) { boxes[i] = MeasureElement(ctx, elements[i]); } else { boxes[i] = BoundingBox.New(); } } return(boxes); }
/** * calculate the required space to fit all the columns */ private static Column[] CreateColumns(IFormattingContext ctx, MathMLMeasurer measurer, MathMLTableCellElement[][] cells, BoundingBox[][] minCellSizes, int columnCount, Length[] columnWidths, Length[] spaceWidths, Length frameSpacing) { Column[] columns = null; int c = 0; int colWidth = 0; int spaceWidth = 0; // new column array: max column count + spacing columns + border spacing // = (max column count) + (max column count - 1) + 2 // = (max column count) + (max column count) + 1 columns = new Column[columnCount + columnCount + 1]; // set the frame spacing columns columns[c++] = new Column(ctx, frameSpacing, 0, true); // outer loop: columns for (int i = 0; i < columnCount; i++) { BoundingBox[] columnCells = new BoundingBox[cells.Length]; // inner loop: rows for (int j = 0; j < cells.Length; j++) { columnCells[j] = i < cells[j].Length ? minCellSizes[j][i] : BoundingBox.New(); } // set the column columns[c++] = new Column(ctx, columnWidths[colWidth++], GetRequiredWidth(columnCells), false); // set the space column if (i < columnCount - 1) { columns[c++] = new Column(ctx, spaceWidths[spaceWidth++], 0, true); } } // set the right spacing column columns[c++] = new Column(ctx, frameSpacing, 0, true); // sanity check Debug.Assert(c == columns.Length, "error, maxColumnCount and processed column count do not match"); return(columns); }
public override AreaRegion GetRegion(IFormattingContext context, float x, float y, MathMLElement element, int index) { float yy = y + BoundingBox.Depth; foreach (Area a in content) { BoundingBox box = a.BoundingBox; yy -= box.Depth; AreaRegion r = a.GetRegion(context, x, yy, element, index); if (r != null) { return(r); } yy -= box.Height; } return(null); }
public override AreaRegion GetRegion(IFormattingContext context, float x, float y, Area area, int index) { if (area == this || area == source) { return(new AreaRegion(this, x, y)); } else { foreach (Area a in content) { AreaRegion r = a.GetRegion(context, x, y, area, index); if (r != null) { return(r); } x += a.BoundingBox.HorizontalExtent; } } return(null); }
public override AreaRegion GetRegion(IFormattingContext context, float x, float y, MathMLElement element, int index) { if(element == this.element) { AreaRegion region = child.GetEditRegion(context, x, y, index); if(region != null) { region.Element = element; } else { Debug.WriteLine("MathMLWrapperArea: child.GetEditRegion returned null, returning new AreaRegion for this area"); region = new AreaRegion(this, element, x, y); } return region; } else { return child.GetRegion(context, x, y, element, index); } }
public override AreaRegion GetRegion(IFormattingContext context, float x, float y, MathMLElement element, int index) { if (element == this.element) { AreaRegion region = child.GetEditRegion(context, x, y, index); if (region != null) { region.Element = element; } else { Debug.WriteLine("MathMLWrapperArea: child.GetEditRegion returned null, returning new AreaRegion for this area"); region = new AreaRegion(this, element, x, y); } return(region); } else { return(child.GetRegion(context, x, y, element, index)); } }
/** * 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); }
/** * 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); }
/** * 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 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; }
/** * create a string area */ public StringArea(IFormattingContext context, string content) { this.font = context.GetFont(); this.content = content; box = BoundingBox.New(); float left = 0, right = 0; for(int i = 0; i < content.Length; i++) { BoundingBox tmp = BoundingBox.New(); context.MeasureGlyph(font, content[i], out tmp, out left, out right); box.Append(tmp); // left edge of first char if(i == 0) { leftEdge = left; } } // right edge of last char rightEdge = right; }
public override AreaRegion GetEditRegion(IFormattingContext context, float x, float y, int index) { foreach(Area a in content) { AreaRegion r = a.GetEditRegion(context, x, y, index); if(r != null) return r; x += a.BoundingBox.HorizontalExtent; } return null; }
public override AreaRegion GetRegion(IFormattingContext context, float x, float y, Area area, int index) { if(area == source) { return new AreaRegion(this, x, y); } else { return child.GetRegion(context, x, y, area, index); } }
public override AreaRegion GetEditRegion(IFormattingContext context, float x, float y, int index) { return null; }
/// <summary> /// Get the child area's terminal node /// </summary> public override AreaRegion GetEditRegion(IFormattingContext context, float x, float y, int index) { return child.GetEditRegion (context, x, y, index); }
public static Area Glyph(IFormattingContext context, String fontName, String altFontName, ushort index) { IFontHandle font = context.GetFont(fontName, altFontName); return new GlyphArea(context, font, index); }
public override AreaRegion GetRegion(IFormattingContext context, float x, float y, Area area, int index) { if(area == this && index <= content.Length) { // measure horizontal position of char: BoundingBox horz = BoundingBox.New(); float left, right; for(int i = 0; i < index; i++) { BoundingBox tmp = BoundingBox.New(); context.MeasureGlyph(font, content[i], out tmp, out left, out right); horz.Append(tmp); } return new AreaRegion(this, x + horz.Width, y); } return null; }
public GlyphArea(IFormattingContext context, IFontHandle font, ushort index) { this.font = font; this.index = index; context.MeasureGlyph(font, index, out box, out leftEdge, out rightEdge); }
public override AreaRegion GetEditRegion(IFormattingContext context, float x, float y, int index) { x = index > 0 ? x + leftEdge + box.HorizontalExtent : x + leftEdge; return new AreaRegion(this, x, y); }
public override AreaRegion GetRegion(IFormattingContext context, float x, float y, Area area, int index) { if(area == this || area == source) { return new AreaRegion(this, x, y); } else { foreach(Area a in content) { AreaRegion r = a.GetRegion(context, x, y, area, index); if(r != null) return r; x += a.BoundingBox.HorizontalExtent; } } return null; }
/** * calculate the default amout the script the baseline of the * script rows. this ignores (for now anyway) the min shift values * specified in the DOM. */ private static void CalculateScriptShift(IFormattingContext context, BoundingBox baseBox, BoundingBox subBox, BoundingBox superBox, out float subShift, out float superShift) { float ex = context.Ex; float axis = context.Axis; float rule = context.DefaultLineThickness; superShift = Math.Max(ex, baseBox.Height - axis); subShift = Math.Max(axis, baseBox.Depth + axis); if(!superBox.Defined) { superShift = 0; subShift = Math.Max(subShift, subBox.Height - (ex * 4.0f) / 5); } else { superShift = Math.Max(superShift, superBox.Depth + ex / 4.0f); if(!subBox.Defined) { subShift = 0; } else { if((superShift - superBox.Depth) - (subBox.Height - superShift) < 4.0f * rule) { subShift = 4.0f * rule - superShift + superBox.Depth + subBox.Height; float psi = (4.0f * ex) / 5.0f - (superShift - superBox.Depth); if(psi > 0.0f) { subShift -= psi; superShift += psi; } } } } }
public override AreaRegion GetRegion(IFormattingContext context, float x, float y, MathMLElement element, int index) { if(element == this.element) { return new AreaRegion(this, element, x + cellShift.X, y + cellShift.Y); } else { return child.GetRegion(context, x + areaShift.X, y + areaShift.Y, element, index); } }
/** * 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; }
public override AreaRegion GetRegion(IFormattingContext context, float x, float y, MathMLElement element, int index) { return child.GetRegion (context, x, y, element, index); }
/** * 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; }
public BoundingBox[][] MeasureElements(IFormattingContext ctx, MathMLElement[][] elements) { BoundingBox[][] boxes = new BoundingBox[elements.Length][]; for(int i = 0; i < elements.Length; i++) { boxes[i] = MeasureElements(ctx, elements[i]); } return boxes; }
public static Area GetStretchyGlyph(IFormattingContext context, float pointSize, char c, BoundingBox desiredSize) { float lineThickness; return GetStretchyGlyph(context, pointSize, c, desiredSize, out lineThickness); }
public BoundingBox[] MeasureElements(IFormattingContext ctx, MathMLElement[] elements) { BoundingBox[] boxes = new BoundingBox[elements.Length]; for(int i = 0; i < elements.Length; i++) { if(elements[i] != null) { boxes[i] = MeasureElement(ctx, elements[i]); } else { boxes[i] = BoundingBox.New(); } } return boxes; }
/** * get a glyph area for this glyph. * this searches through the glyphs list to see * if an area has allready been created for the mathing * set of glyph index and font, if none exists, a new * glyph area is created and cached via a weak reference. */ public Area GetArea(IFormattingContext context, IFontHandle fontHandle) { return new GlyphArea(context, fontHandle, GlyphIndex); }
public override AreaRegion GetRegion(IFormattingContext context, float x, float y, MathMLElement element, int index) { float yy = y + BoundingBox.Depth; foreach(Area a in content) { BoundingBox box = a.BoundingBox; yy -= box.Depth; AreaRegion r = a.GetRegion(context, x, yy, element, index); if(r != null) { return r; } yy -= box.Height; } return null; }
/** * 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}); }