private void DrawTextLine( DrawingContext drawingContext, Point origin, MatrixTransform antiInversion ) { Rect boundingBox = Rect.Empty; if (_ploline.Value != System.IntPtr.Zero) { TextFormatterContext context; LsErr lserr = LsErr.None; LSRECT rect = new LSRECT(0, 0, _metrics._textWidthAtTrailing, _metrics._height); // DrawingState needs to be properly disposed after performing actual drawing operations. using (DrawingState drawingState = new DrawingState(drawingContext, origin, antiInversion, this)) { context = _metrics._formatter.AcquireContext( drawingState, _ploc.Value ); // set the collector and send the line to LS to draw context.EmptyBoundingBox(); // LS line reference origin LSPOINT lsRefOrigin = new LSPOINT(0, _metrics._baselineOffset); lserr = UnsafeNativeMethods.LoDisplayLine( _ploline.Value, ref lsRefOrigin, 1, // 0 - opaque, 1 - transparent ref rect ); } boundingBox = context.BoundingBox; // get the exception in context before it is released Exception callbackException = context.CallbackException; context.Release(); if(lserr != LsErr.None) { if(callbackException != null) { // rethrow exception thrown in callbacks throw callbackException; } else { // throw with LS error codes TextFormatterContext.ThrowExceptionFromLsError(SR.Get(SRID.CreateLineFailure, lserr), lserr); } } // keep context alive at least til here GC.KeepAlive(context); } if (_collapsingSymbol != null) { // draw collapsing symbol if any Point vectorToOrigin = new Point(); if (antiInversion != null) { vectorToOrigin = origin; origin.X = origin.Y = 0; } boundingBox.Union(DrawCollapsingSymbol(drawingContext, origin, vectorToOrigin)); } BuildOverhang(origin, boundingBox); _statusFlags |= StatusFlags.BoundingBoxComputed; }
internal unsafe LsErr DrawGlyphs( IntPtr pols, // Line Layout context Plsrun plsrun, // plsrun char* pwchText, // character string ushort* puClusterMap, // character-to-cluster map ushort* puCharProperties, // character properties int charCount, // character count ushort* puGlyphs, // glyph indices int* piJustifiedGlyphAdvances, // justified glyph advances int* piGlyphAdvances, // original ideal glyph advances GlyphOffset* piiGlyphOffsets, // glyph offsets uint* piGlyphProperties, // glyph properties LsExpType* plsExpType, // glyph expansion types int glyphCount, // glyph count LsTFlow textFlow, // text flow uint displayMode, // draw transparent or opaque ref LSPOINT ptRun, // [in] display position (at baseline) ref LsHeights lsHeights, // [in] run height metrics int runWidth, // run overall advance width ref LSRECT clippingRect // [in] clipping rectangle if any applied ) { LsErr lserr = LsErr.None; LSRun lsrun = null; try { TextMetrics.FullTextLine currentLine = Draw.CurrentLine; lsrun = currentLine.GetRun(plsrun); Debug.Assert(TextStore.IsContent(plsrun) && lsrun.Shapeable != null); GlyphRun glyphRun = ComputeShapedGlyphRun( lsrun, currentLine.Formatter, true, // origin of the glyph run provided at drawing time ptRun, charCount, pwchText, puClusterMap, glyphCount, puGlyphs, piJustifiedGlyphAdvances, piiGlyphOffsets, currentLine.IsJustified ); if (glyphRun != null) { DrawingContext drawingContext = Draw.DrawingContext; Draw.SetGuidelineY(glyphRun.BaselineOrigin.Y); try { _boundingBox.Union( lsrun.DrawGlyphRun( drawingContext, null, // draw with the run's foreground glyphRun ) ); } finally { Draw.UnsetGuidelineY(); } } } catch (Exception e) { SaveException(e, plsrun, lsrun); lserr = LsErr.ClientAbort; } catch { SaveNonCLSException("DrawGlyphs", plsrun, lsrun); lserr = LsErr.ClientAbort; } return lserr; }
internal unsafe LsErr DrawTextRun( IntPtr pols, // Line Layout context Plsrun plsrun, // plsrun ref LSPOINT ptText, // [in] text origin char* pwchText, // character string int* piCharAdvances, // char advance widths int cchText, // text length LsTFlow textFlow, // text flow uint displayMode, // draw in transparent or opaque ref LSPOINT ptRun, // [in] run origin ref LsHeights lsHeights, // [in] run height int dupRun, // run length ref LSRECT clipRect // [in] from DisplayLine's clip rectangle param ) { LsErr lserr = LsErr.None; LSRun lsrun = null; try { TextMetrics.FullTextLine currentLine = Draw.CurrentLine; lsrun = currentLine.GetRun(plsrun); GlyphRun glyphRun = ComputeUnshapedGlyphRun( lsrun, textFlow, currentLine.Formatter, true, // origin of the glyph run provided at drawing time ptText, dupRun, cchText, pwchText, piCharAdvances, currentLine.IsJustified ); if (glyphRun != null) { DrawingContext drawingContext = Draw.DrawingContext; Draw.SetGuidelineY(glyphRun.BaselineOrigin.Y); try { _boundingBox.Union( lsrun.DrawGlyphRun( drawingContext, null, // draw with the run's foreground brush glyphRun ) ); } finally { Draw.UnsetGuidelineY(); } } } catch (Exception e) { SaveException(e, plsrun, lsrun); lserr = LsErr.ClientAbort; } catch { SaveNonCLSException("DrawTextRun", plsrun, lsrun); lserr = LsErr.ClientAbort; } return lserr; }
internal LsErr DrawUnderline( IntPtr pols, // Line Layout context Plsrun plsrun, // plsrun uint ulType, // kind of underline ref LSPOINT ptOrigin, // [in] drawing origin int ulLength, // underline length int ulThickness, // underline thickness LsTFlow textFlow, // text flow direction uint displayMode, // display mode ref LSRECT clipRect // [in] clipping rectangle ) { LsErr lserr = LsErr.None; LSRun lsrun = null; try { if (!TextStore.IsContent(plsrun)) { return LsErr.None; } lsrun = Draw.CurrentLine.GetRun(plsrun); const uint locationMask = (1U << (int)TextDecorationLocation.Underline); DrawTextDecorations( lsrun, locationMask, ptOrigin.x, // left ptOrigin.y, // underline top from LS 0, // overline top; not used 0, // strikethrough top; not used 0, // baseline top; not used ulLength, ulThickness, textFlow ); } catch (Exception e) { SaveException(e, plsrun, lsrun); lserr = LsErr.ClientAbort; } catch { SaveNonCLSException("DrawUnderline", plsrun, lsrun); lserr = LsErr.ClientAbort; } return lserr; }
internal LsErr DrawStrikethrough( IntPtr pols, // Line Layout context Plsrun plsrun, // plsrun uint stType, // kind of strike ref LSPOINT ptOrigin, // [in] drawing origin int stLength, // strike length int stThickness, // strike thickness LsTFlow textFlow, // text flow direction uint displayMode, // display mode ref LSRECT clipRect // [in] clipping rectangle ) { LsErr lserr = LsErr.None; LSRun lsrun = null; try { if (!TextStore.IsContent(plsrun)) { return LsErr.None; } TextMetrics.FullTextLine currentLine = Draw.CurrentLine; lsrun = currentLine.GetRun(plsrun); double strikeThroughPositionInEm; double strikeThroughThicknessInEm; GetLSRunStrikethroughMetrics(lsrun, out strikeThroughPositionInEm, out strikeThroughThicknessInEm); int baselineTop = ptOrigin.y + (int)Math.Round(lsrun.EmSize * strikeThroughPositionInEm); int overlineTop = baselineTop - (lsrun.BaselineOffset - (int)Math.Round(lsrun.EmSize * strikeThroughThicknessInEm)); const uint locationMask = (1U << (int)TextDecorationLocation.OverLine) | (1U << (int)TextDecorationLocation.Strikethrough) | (1U << (int)TextDecorationLocation.Baseline); DrawTextDecorations( lsrun, locationMask, ptOrigin.x, // left 0, // underline top; not used overlineTop, ptOrigin.y, // strikethrough top from LS baselineTop, stLength, stThickness, textFlow ); } catch (Exception e) { SaveException(e, plsrun, lsrun); lserr = LsErr.ClientAbort; } catch { SaveNonCLSException("DrawStrikethrough", plsrun, lsrun); lserr = LsErr.ClientAbort; } return lserr; }
internal static extern LsErr LoDisplayLine( IntPtr ploline, ref LSPOINT pt, uint displayMode, ref LSRECT clipRect );