简体   繁体   English

计算OpenXML(PresentationML)PowerPoint(PPTX)中文本(TextBody)的大小(范围)

[英]Calculate the size (Extents) of a text (TextBody) in OpenXML (PresentationML) PowerPoint (PPTX)

I want to create a presentation with data coming from a database. 我想使用来自数据库的数据创建演示文稿。 I manage to get valid presentations that open in PowerPoint (the Open XML Productivity Tool of the SDK 2.5 is a big help in doing this). 我设法获得了在PowerPoint中打开的有效演示文稿(SDK 2.5的Open XML Productivity Tool在执行此操作方面有很大帮助)。 But, how to calculate the size of the textbox shapes? 但是,如何计算文本框形状的大小? I see where to put the values, but new Extents() defaults to zero width and height. 我看到将值放在哪里,但是new Extents()默认为零宽度和高度。 When I take some values of a Shape from an existing presentation, I may get the correct height (at least for texts with one line or a fixed number of lines), but the text will overflow to the right or at the bottom (depending on wordwrap setting). 当我从现有演示文稿中获取一些Shape值时,我可能会得到正确的高度(至少对于一行或固定行数的文本而言),但是文本会在右侧或底部溢出(取决于换行设置)。

Also inserting NormalAutoFit in the BodyProperties of the TextBody doesn't help - the necessary values for FontScale and LineSpaceReduction aren't calculated in OpenXML. 另外,在TextBodyBodyProperties中插入NormalAutoFit也无济于事-在OpenXML中不计算FontScaleLineSpaceReduction的必要值。

So, what's best practice for setting the Extents of a Shape with a TextBody ? 那么,用TextBody设置ShapeExtents的最佳实践是什么?

Is there a built-in way to calculate the Extents of a given TextBody or Shape ? 是否有一个内置的方式来计算Extents给定的TextBodyShape (some rule of thumb with built-in methods would be better than nothing) (一些内置方法的经验法则总比没有好。)

I know that PowerPoint will recalculate the values of NormalAutoFit after any change was made (at least for a bunch of slides before and after that change), but this doesn't help when the presentation is started before a change was made (or if it was started with the PowerPoint viewer). 我知道PowerPoint会在进行任何更改后(至少对于更改前后的一堆幻灯片)重新计算NormalAutoFit的值, NormalAutoFit在进行更改之前开始演示文稿(或是否进行更改)没有帮助。是使用PowerPoint查看器启动的)。

From Eric White's Forum 埃里克·怀特(Eric White)的论坛

This is a non-trivial (but doable) task. 这是一项艰巨(但可行)的任务。

After many experiments, I found that the text metrics methods in System.Windows.Forms.TextRenderer gave me the best results. 经过多次实验,我发现System.Windows.Forms.TextRenderer中的文本度量方法给了我最好的结果。 This is the text metric functionality that WmlToHtmlConverter uses. 这是WmlToHtmlConverter使用的文本度量功能。 You can look at the code in WmlToHtmlConverter as one example of the use of TextRenderer. 您可以将WmlToHtmlConverter中的代码视为使用TextRenderer的一个示例。

Here's the code I've come up with for my purposes based on Eric White's WmlToHtmlConverter, this post and this . 这是我根据Eric White的WmlToHtmlConverter, 本文this提出的代码 I use this to calculate the dimensions of TextBox for text watermarks and for image watermarks for OpenXml for Word documents. 我用它来计算用于Word文档的OpenXml的文本水印和图像水印的TextBox的尺寸。

    private static D.Size pixelsToEmus(int widthPx, int heightPx, double resDpiX, double resDpiY, int zoomX, int zoomY)
    {
        const int emusPerInch = 914400;
        const int emusPerCm = 360000;
        const decimal maxWidthCm = 16.51m;
        var widthEmus = (int)(widthPx / resDpiX * emusPerInch) * zoomX / 100;
        var heightEmus = (int)(heightPx / resDpiY * emusPerInch) * zoomY / 100;
        var maxWidthEmus = (int)(maxWidthCm * emusPerCm);
        if (widthEmus > maxWidthEmus)
        {
            var ratio = ((decimal)heightEmus / (decimal)widthEmus);
            widthEmus = maxWidthEmus;
            heightEmus = (int)(widthEmus * ratio);
        }
        return new D.Size(widthEmus, heightEmus);
    }

    public static D.Size GetTextSize(this CWatermarkItemBase watermark, string runText)
    {
        var fs = watermark.GetFontStyle();
        var sz = watermark.FontSize;
        var proposedSize = new D.Size(int.MaxValue, int.MaxValue);
        D.Size sf;

        using (var ff = new D.FontFamily(watermark.FontFamily))
        {
            try
            {
                using (var f = new D.Font(ff, (float)sz, fs))
                {
                    const TextFormatFlags tff = TextFormatFlags.NoPadding;
                    sf = TextRenderer.MeasureText(runText, f, proposedSize, tff);
                }
            }
            catch (ArgumentException)
            {
                try
                {
                    const D.FontStyle fs2 = D.FontStyle.Regular;
                    using (D.Font f = new D.Font(ff, (float)sz, fs2))
                    {
                        const TextFormatFlags tff = TextFormatFlags.NoPadding;
                        sf = TextRenderer.MeasureText(runText, f, proposedSize, tff);
                    }
                }
                catch (ArgumentException)
                {
                    const D.FontStyle fs2 = D.FontStyle.Bold;
                    try
                    {
                        using (var f = new D.Font(ff, (float)sz, fs2))
                        {
                            const TextFormatFlags tff = TextFormatFlags.NoPadding;
                            sf = TextRenderer.MeasureText(runText, f, proposedSize, tff);
                        }
                    }
                    catch (ArgumentException)
                    {
                        // if both regular and bold fail, then get metrics for Times New Roman
                        // use the original FontStyle (in fs)
                        using (var ff2 = new D.FontFamily("Times New Roman"))
                        using (var f = new D.Font(ff2, (float)sz, fs))
                        {
                            const TextFormatFlags tff = TextFormatFlags.NoPadding;
                            sf = TextRenderer.MeasureText(runText, f, proposedSize, tff);
                        }
                    }
                }
            }
        }
        D.Size s2 = pixelsToEmus(sf.Width, sf.Height, 96, 96, 100, 100);
        return s2;
    }
    public static D.Size GetImageSize(this CWatermarkItemImage watermarkItem)
    {
        var img = new BitmapImage(new Uri(watermarkItem.FilePath, UriKind.RelativeOrAbsolute));
        return pixelsToEmus(img.PixelWidth, img.PixelHeight, img.DpiX, img.DpiY, watermarkItem.ZoomWidth, watermarkItem.ZoomHeight);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM