/** * 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; } }
/** * 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; } }
public GlyphArea(IFontHandle fontHandle, ref GlyphAttributes attributes) { this.font = fontHandle; this.leftEdge = attributes.Left; this.rightEdge = attributes.Right; this.box = attributes.Box; this.index = (ushort)attributes.Index; }
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 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]); } }
private Area[] StretchBottom(IFontHandle fontHandle, BoundingBox box) { Area[] result; Area filler = compoundGlyphs[StretchyGlyphIndices.Filler].GetGlyph(fontHandle); float availSpace = (orientation == StretchyOrientation.Vertical ? box.VerticalExtent - compoundGlyphs[StretchyGlyphIndices.Bottom].Box.VerticalExtent : box.Width = compoundGlyphs[StretchyGlyphIndices.Bottom].Box.Width); int fillerCount = GetFillerCount(availSpace); result = new Area[fillerCount + 1]; result[0] = compoundGlyphs[StretchyGlyphIndices.Bottom].GetGlyph(fontHandle); for (int i = 1; i < result.Length; i++) { result[i] = filler; } return(result); }
/** * try to find a font in the list that matches the contents * of the formating context */ private IFontHandle FindFont(float height, bool italic, int weight, string fontName) { for (int i = 0; i < fonts.Count; i++) { WeakReference w = (WeakReference)fonts[i]; if (w.IsAlive) { IFontHandle f = (IFontHandle)w.Target; if (f.Equals(height, italic, weight, fontName)) { return(f); } } else { // reference is dead, so get rid of it fonts.RemoveAt(i--); } } // no font was found return(null); }
private Area[] StretchFillerOnly(IFontHandle fontHandle, BoundingBox box) { int fillerCount; Area[] result; Area filler = compoundGlyphs[StretchyGlyphIndices.Filler].GetGlyph(fontHandle); if (orientation == StretchyOrientation.Vertical) { fillerCount = GetFillerCount(box.VerticalExtent); } else { fillerCount = GetFillerCount(box.HorizontalExtent); } result = new Area[fillerCount]; for (int i = 0; i < result.Length; i++) { result[i] = filler; } 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; }
/** * search through all of the simple glyphs for this character, and * return the first one that is just larger that the requested * size. return null if no mathching glyph is found */ private Area GetSimpleArea(IFontHandle fontHandle, BoundingBox desiredSize) { if (orientation == StretchyOrientation.Vertical) { for (int i = 0; i < simpleGlyphs.Length; i++) { if (simpleGlyphs[i].Box.VerticalExtent >= desiredSize.VerticalExtent) { return(simpleGlyphs[i].GetGlyph(fontHandle)); } } } else { for (int i = 0; i < simpleGlyphs.Length; i++) { if (simpleGlyphs[i].Box.HorizontalExtent >= desiredSize.HorizontalExtent) { return(simpleGlyphs[i].GetGlyph(fontHandle)); } } } return(null); }
/** * 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; }
/** * try to get a stretchy glyph 3 different ways, first try to find a * simple glyph that is just larger than the desired size. If we can * not find a simple glyph, we try to fit together a compound glyph * by repeating the filler area. If that fails, the last resort is * to just get the largest simple glyph. * * once a glyph is found, it is centered in the desiredSize region. */ public Area GetStretchyArea(IFontHandle fontHandle, BoundingBox desiredSize, out float lineThickness) { Area result = null; if ((result = GetSimpleArea(fontHandle, desiredSize)) == null) { if ((result = GetCompoundArea(fontHandle, desiredSize)) == null) { result = GetLargestSimpleArea(fontHandle); } } if (result != null) { lineThickness = GetLineThickness(); result = ShiftArea(result, desiredSize); } else { lineThickness = 0.0f; } return(result); }
private Area GetCompoundArea(IFontHandle fontHandle, BoundingBox desiredSize) { Area[] areas = null; if (compoundGlyphs[StretchyGlyphIndices.Bottom].Index >= 0) { if (compoundGlyphs[StretchyGlyphIndices.Top].Index >= 0) { if (compoundGlyphs[StretchyGlyphIndices.Middle].Index >= 0) { areas = StretchBottomMiddleTop(fontHandle, desiredSize); } else { areas = StretchBottomTop(fontHandle, desiredSize); } } else { areas = StretchBottom(fontHandle, desiredSize); } } else { if (compoundGlyphs[StretchyGlyphIndices.Top].Index >= 0) { areas = StretchTop(fontHandle, desiredSize); } else { areas = StretchFillerOnly(fontHandle, desiredSize); } } return(orientation == StretchyOrientation.Vertical ? (Area)(new VerticalCompoundGlyph(null, areas, 0)) : (Area)(new HorizontalCompoundGlyph(areas))); }
/** * 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); }
private Area[] StretchFillerOnly(IFontHandle fontHandle, BoundingBox box) { int fillerCount; Area[] result; Area filler = compoundGlyphs[StretchyGlyphIndices.Filler].GetGlyph(fontHandle); if(orientation == StretchyOrientation.Vertical) { fillerCount = GetFillerCount(box.VerticalExtent); } else { fillerCount = GetFillerCount(box.HorizontalExtent); } result = new Area[fillerCount]; for(int i = 0; i < result.Length; i++) { result[i] = filler; } return result; }
private Area[] StretchBottomMiddleTop(IFontHandle fontHandle, BoundingBox box) { float availSpace; Area[] result; Area filler = compoundGlyphs[StretchyGlyphIndices.Filler].GetGlyph(fontHandle); if(orientation == StretchyOrientation.Vertical) { availSpace = box.VerticalExtent - ( compoundGlyphs[StretchyGlyphIndices.Bottom].Box.VerticalExtent + compoundGlyphs[StretchyGlyphIndices.Middle].Box.VerticalExtent + compoundGlyphs[StretchyGlyphIndices.Top].Box.VerticalExtent); } else { availSpace = box.Width - ( compoundGlyphs[StretchyGlyphIndices.Bottom].Box.Width + compoundGlyphs[StretchyGlyphIndices.Middle].Box.Width + compoundGlyphs[StretchyGlyphIndices.Top].Box.Width); } // use halfFillerCount to prevent compiler optimizations // from removing divide multiply by 2 int halfFillerCount = GetFillerCount(availSpace) / 2; // bump the filler count if we are short of the availible space if(halfFillerCount * 2 * (orientation == StretchyOrientation.Vertical ? filler.BoundingBox.VerticalExtent : filler.BoundingBox.Width) < availSpace) { halfFillerCount++; } result = new Area[2 * halfFillerCount + 3]; result[0] = compoundGlyphs[StretchyGlyphIndices.Bottom].GetGlyph(fontHandle); for(int i = 1; i < halfFillerCount + 1; i++) { result[i] = filler; } result[halfFillerCount + 1] = compoundGlyphs[StretchyGlyphIndices.Middle].GetGlyph(fontHandle); for(int i = halfFillerCount + 2; i < result.Length - 1; i++) { result[i] = filler; } result[result.Length - 1] = compoundGlyphs[StretchyGlyphIndices.Top].GetGlyph(fontHandle); return result; }
private Area[] StretchBottomTop(IFontHandle fontHandle, BoundingBox box) { float availSpace; int fillerCount; Area[] result; Area filler = compoundGlyphs[StretchyGlyphIndices.Filler].GetGlyph(fontHandle); if(orientation == StretchyOrientation.Vertical) { availSpace = box.VerticalExtent - (compoundGlyphs[StretchyGlyphIndices.Bottom].Box.VerticalExtent + compoundGlyphs[StretchyGlyphIndices.Top].Box.VerticalExtent); } else { availSpace = box.Width - (compoundGlyphs[StretchyGlyphIndices.Bottom].Box.Width + compoundGlyphs[StretchyGlyphIndices.Top].Box.Width); } fillerCount = GetFillerCount(availSpace); result = new Area[fillerCount + 2]; result[0] = compoundGlyphs[StretchyGlyphIndices.Bottom].GetGlyph(fontHandle); for(int i = 1; i < result.Length - 1; i++) { result[i] = filler; } result[result.Length - 1] = compoundGlyphs[StretchyGlyphIndices.Top].GetGlyph(fontHandle); Debug.WriteLine(String.Format("found bottom-top compound area, {0} filler areas", fillerCount)); return result; }
private Area[] StretchTop(IFontHandle fontHandle, BoundingBox box) { Area[] result; Area filler = compoundGlyphs[StretchyGlyphIndices.Filler].GetGlyph(fontHandle); float availSpace = (orientation == StretchyOrientation.Vertical ? box.VerticalExtent - compoundGlyphs[StretchyGlyphIndices.Top].Box.VerticalExtent : box.Width = compoundGlyphs[StretchyGlyphIndices.Top].Box.Width); int fillerCount = GetFillerCount(availSpace); result = new Area[fillerCount + 1]; for(int i = 0; i < result.Length - 1; i++) { result[i] = filler; } result[result.Length - 1] = compoundGlyphs[StretchyGlyphIndices.Top].GetGlyph(fontHandle); return result; }
/** * Sets the given font as the curent active font. * @param font a native font resource returned from GetFont * @return The previous font. This font MUST BE RESTORED when the new * font is no longer used */ public IFontHandle SetFont(IFontHandle font) { IFontHandle result = currentFont; currentFont = font; return result; }
private Area GetCompoundArea(IFontHandle fontHandle, BoundingBox desiredSize) { Area[] areas = null; if(compoundGlyphs[StretchyGlyphIndices.Bottom].Index >= 0) { if(compoundGlyphs[StretchyGlyphIndices.Top].Index >= 0) { if(compoundGlyphs[StretchyGlyphIndices.Middle].Index >= 0) { areas = StretchBottomMiddleTop(fontHandle, desiredSize); } else { areas = StretchBottomTop(fontHandle, desiredSize); } } else { areas = StretchBottom(fontHandle, desiredSize); } } else { if(compoundGlyphs[StretchyGlyphIndices.Top].Index >= 0) { areas = StretchTop(fontHandle, desiredSize); } else { areas = StretchFillerOnly(fontHandle, desiredSize); } } return orientation == StretchyOrientation.Vertical ? (Area)(new VerticalCompoundGlyph(null, areas, 0)) : (Area)(new HorizontalCompoundGlyph(areas)); }
/** * search through all of the simple glyphs for this character, and * return the first one that is just larger that the requested * size. return null if no mathching glyph is found */ private Area GetSimpleArea(IFontHandle fontHandle, BoundingBox desiredSize) { if(orientation == StretchyOrientation.Vertical) { for(int i = 0; i < simpleGlyphs.Length; i++) { if(simpleGlyphs[i].Box.VerticalExtent >= desiredSize.VerticalExtent) { return simpleGlyphs[i].GetGlyph(fontHandle); } } } else { for(int i = 0; i < simpleGlyphs.Length; i++) { if(simpleGlyphs[i].Box.HorizontalExtent >= desiredSize.HorizontalExtent) { return simpleGlyphs[i].GetGlyph(fontHandle); } } } return null; }
public Area GetGlyph(IFontHandle fontHandle) { Area result = null; if(glyphArea != null && glyphArea.IsAlive) { result = (Area)glyphArea.Target; } else { result = new GlyphArea(fontHandle, ref this); glyphArea = new WeakReference(result); } return result; }
/** * 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)); }
/** * get the dpi resolution of the current device */ /* * public Scaled Dpi * { * get * {// TODO is this right? * return 72.0f; * } * } */ public bool MeasureGlyph(IFontHandle font, ushort index, out BoundingBox box, out Scaled left, out Scaled right) { return(MeasureGlyph(_graphics, font, index, out box, out left, out right)); }
public GlyphArea(IFormattingContext context, IFontHandle font, ushort index) { this.font = font; this.index = index; context.MeasureGlyph(font, index, out box, out leftEdge, out rightEdge); }
private Area GetLargestSimpleArea(IFontHandle fontHandle) { Area result = null; if(simpleGlyphs.Length > 0) { result = simpleGlyphs[simpleGlyphs.Length - 1].GetGlyph(fontHandle); } return result; }
/** * try to get a stretchy glyph 3 different ways, first try to find a * simple glyph that is just larger than the desired size. If we can * not find a simple glyph, we try to fit together a compound glyph * by repeating the filler area. If that fails, the last resort is * to just get the largest simple glyph. * * once a glyph is found, it is centered in the desiredSize region. */ public Area GetStretchyArea(IFontHandle fontHandle, BoundingBox desiredSize, out float lineThickness) { Area result = null; if((result = GetSimpleArea(fontHandle, desiredSize)) == null) { if((result = GetCompoundArea(fontHandle, desiredSize)) == null) { result = GetLargestSimpleArea(fontHandle); } } if(result != null) { lineThickness = GetLineThickness(); result = ShiftArea(result, desiredSize); } else { lineThickness = 0.0f; } return result; }
/** * restores a font previously returned from SetFont */ public void RestoreFont(IFontHandle font) { // note, font resource are not destroyed here. font // resources are cached in the fonts list, and are // destroyed when this object is told to clear them. currentFont = font; }
/** * get the dpi resolution of the current device */ /* public Scaled Dpi { get {// TODO is this right? return 72.0f; } } */ public bool MeasureGlyph(IFontHandle font, ushort index, out BoundingBox box, out Scaled left, out Scaled right) { return MeasureGlyph(_graphics, font, index, out box, out left, out right); }