CN1989543A - 媒体集成层 - Google Patents

媒体集成层 Download PDF

Info

Publication number
CN1989543A
CN1989543A CNA2004800014899A CN200480001489A CN1989543A CN 1989543 A CN1989543 A CN 1989543A CN A2004800014899 A CNA2004800014899 A CN A2004800014899A CN 200480001489 A CN200480001489 A CN 200480001489A CN 1989543 A CN1989543 A CN 1989543A
Authority
CN
China
Prior art keywords
public
visual element
function
scene graph
data structure
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Pending
Application number
CNA2004800014899A
Other languages
English (en)
Inventor
S·萨布拉马尼安
L·E·布兰克
D·B·柯蒂斯
J·S·比答
G·A·施奈德
G·D·谢齐特
A·M·史密斯
E·S·范登伯格
M·W·卡尔金斯
K·T·加罗
M·斯托克斯
R·戈尔
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Microsoft Corp
Original Assignee
Microsoft Corp
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Microsoft Corp filed Critical Microsoft Corp
Publication of CN1989543A publication Critical patent/CN1989543A/zh
Pending legal-status Critical Current

Links

Images

Classifications

    • GPHYSICS
    • G09EDUCATION; CRYPTOGRAPHY; DISPLAY; ADVERTISING; SEALS
    • G09GARRANGEMENTS OR CIRCUITS FOR CONTROL OF INDICATING DEVICES USING STATIC MEANS TO PRESENT VARIABLE INFORMATION
    • G09G5/00Control arrangements or circuits for visual indicators common to cathode-ray tube indicators and other visual indicators
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06TIMAGE DATA PROCESSING OR GENERATION, IN GENERAL
    • G06T17/00Three dimensional [3D] modelling, e.g. data description of 3D objects
    • G06T17/005Tree description, e.g. octree, quadtree
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/46Multiprogramming arrangements
    • G06F9/54Interprogram communication
    • G06F9/545Interprogram communication where tasks reside in different layers, e.g. user- and kernel-space
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06TIMAGE DATA PROCESSING OR GENERATION, IN GENERAL
    • G06T13/00Animation
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F3/00Input arrangements for transferring data to be processed into a form capable of being handled by the computer; Output arrangements for transferring data from processing unit to output unit, e.g. interface arrangements
    • G06F3/14Digital output to display device ; Cooperation and interconnection of the display device with other functional units
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06TIMAGE DATA PROCESSING OR GENERATION, IN GENERAL
    • G06T2210/00Indexing scheme for image generation or computer graphics
    • G06T2210/08Bandwidth reduction
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06TIMAGE DATA PROCESSING OR GENERATION, IN GENERAL
    • G06T2210/00Indexing scheme for image generation or computer graphics
    • G06T2210/61Scene description
    • GPHYSICS
    • G09EDUCATION; CRYPTOGRAPHY; DISPLAY; ADVERTISING; SEALS
    • G09GARRANGEMENTS OR CIRCUITS FOR CONTROL OF INDICATING DEVICES USING STATIC MEANS TO PRESENT VARIABLE INFORMATION
    • G09G2340/00Aspects of display data processing
    • G09G2340/04Changes in size, position or resolution of an image
    • GPHYSICS
    • G09EDUCATION; CRYPTOGRAPHY; DISPLAY; ADVERTISING; SEALS
    • G09GARRANGEMENTS OR CIRCUITS FOR CONTROL OF INDICATING DEVICES USING STATIC MEANS TO PRESENT VARIABLE INFORMATION
    • G09G2340/00Aspects of display data processing
    • G09G2340/04Changes in size, position or resolution of an image
    • G09G2340/0407Resolution change, inclusive of the use of different resolutions for different screen areas
    • GPHYSICS
    • G09EDUCATION; CRYPTOGRAPHY; DISPLAY; ADVERTISING; SEALS
    • G09GARRANGEMENTS OR CIRCUITS FOR CONTROL OF INDICATING DEVICES USING STATIC MEANS TO PRESENT VARIABLE INFORMATION
    • G09G2340/00Aspects of display data processing
    • G09G2340/04Changes in size, position or resolution of an image
    • G09G2340/0407Resolution change, inclusive of the use of different resolutions for different screen areas
    • G09G2340/0414Vertical resolution change
    • GPHYSICS
    • G09EDUCATION; CRYPTOGRAPHY; DISPLAY; ADVERTISING; SEALS
    • G09GARRANGEMENTS OR CIRCUITS FOR CONTROL OF INDICATING DEVICES USING STATIC MEANS TO PRESENT VARIABLE INFORMATION
    • G09G2340/00Aspects of display data processing
    • G09G2340/04Changes in size, position or resolution of an image
    • G09G2340/0407Resolution change, inclusive of the use of different resolutions for different screen areas
    • G09G2340/0421Horizontal resolution change
    • GPHYSICS
    • G09EDUCATION; CRYPTOGRAPHY; DISPLAY; ADVERTISING; SEALS
    • G09GARRANGEMENTS OR CIRCUITS FOR CONTROL OF INDICATING DEVICES USING STATIC MEANS TO PRESENT VARIABLE INFORMATION
    • G09G2340/00Aspects of display data processing
    • G09G2340/04Changes in size, position or resolution of an image
    • G09G2340/0407Resolution change, inclusive of the use of different resolutions for different screen areas
    • G09G2340/0428Gradation resolution change
    • GPHYSICS
    • G09EDUCATION; CRYPTOGRAPHY; DISPLAY; ADVERTISING; SEALS
    • G09GARRANGEMENTS OR CIRCUITS FOR CONTROL OF INDICATING DEVICES USING STATIC MEANS TO PRESENT VARIABLE INFORMATION
    • G09G2340/00Aspects of display data processing
    • G09G2340/04Changes in size, position or resolution of an image
    • G09G2340/0464Positioning

Abstract

包括应用编程接口(API)和对象模型的媒体集成层允许程序代码开发者以一致的方式与场景图数据结构连接,以便输出图形。通过接口,程序代码将子视件加到其它视件上来组成分层的场景图,编写指令表诸如几何图形数据、图像数据、动画数据和其它输出数据,并可指定视件上的变换、剪辑和不透明性属性。媒体集成层和API使程序员在他们的应用程序中以直接方式完成合成效果,同时以没有不利地影响正常应用程序性能的方式利用图形处理单元。多层系统包括使不同媒体类型(诸如2D、3D、视频、音频、文本和成像)组合起来并使它们平滑无缝地形成动画的能力。

Description

媒体集成层
技术领域
本发明一般涉及计算机系统,且特别涉及为在计算机系统上显示而进行的对图形和其它视频信息的处理。
背景技术
在计算机系统上传统的访问图形的立即模式模型的极限正在到达,部分是因为存储器和总线速度跟不上在主处理器和/或图形处理器方面的进步。通常,当想要复杂的图形效果时,为了跟上硬件刷新速度,用于准备一个帧的当前(例如,WM_PAINT)模型需要太多的数据处理。结果,当用传统的图形模型来尝试复杂图形效果时,不是完成了及时导致下一个帧的感知视觉效果的变化,而是可能将变化加在了不同的帧上,引起在视觉上显然不想要的结果。
在美国专利申请序列号10/184,795、10/184,796、10/185,775、10/401,717、10/402,322和10/402,268中描述了控制图形输出的新模型,它们都转让给本发明的代理人并通过引用包含在此。这个新模型在图形处理技术方面提供了许多显著的改进。例如,美国序列号10/184,795主要针对多层图形处理系统和方法,其中较高层组件(例如,操作系统的)以相对低的操作速度完成构建场景图、更新动画参数及遍历场景图的数据结构等计算密集的方面,以便将简化的数据结构和/或图形命令传递给低层组件。由于高层处理大大简化了数据,低层组件能以较快的速度(相对于高层组件),诸如以相应于图形子系统的帧刷新速度运行,将数据处理成图形子系统的持续输出数据。当使用动画时,取代必须重新绘制具有变化的整个场景,低层处理可按需要内插参数间隔,以获得当呈现时为每个帧提供轻微改变的场景的瞬时值,从而提供平滑的动画。
美国序列号10/184,796描述了参数化场景图,它提供了可变(动画)值和参数化的图形容器,使得想要绘制图形的程序代码(例如,应用程序或操作系统组件)可有选择地改变场景图描述的某些方面,同时使其它方面保持不变。程序代码还可用可能不同的参数来重新使用场景图的已构建部分。可以理解,通过参数化和/或重新使用场景图的现有部分容易地改变显示项外观的能力提供了在整个图形处理效率上的大幅增长。
美国序列号10/185,775主要描述了高速缓存数据结构和有关的机制,用于通过场景图中的对象和数据存储视觉信息。数据结构主要关联于智能控制如何在其中填充和使用视觉信息的机制。例如,除非应用程序明确请求,大多数存储在数据结构中的信息没有对它的外部引用,这使得这个信息可被优化或处理。可以理解,这提供了效率和资源的保存,例如,可以将高速缓存数据结构中的数据处理成更紧凑的不同格式和/或减少后续重复处理诸如位图或其它后处理结果的需求。
尽管以上改进在图形处理技术方面提供了重大益处,但还是需要一种方法,使程序以直接方式有效地利用这个改进的图形模型及其其它有关改进。所需要的是一个全面而直接的模型,使程序利用由改进的图形模型提供的许多特征和图形处理能力并由此以有效方式输出复杂图形和音视频数据。
发明概述
简而言之,本发明提供了一种媒体集成层,它为程序员提供了API来在他们的应用程序中以直接方式完成可能复杂的合成效果,同时以不会不利地影响正常应用程序性能的方式利用图形处理单元。一个方面提供了将不同媒体类型(例如,2D、3D、视频、音频、文本、成像等)组合起来并让它们一起平滑无缝地形成动画。
MIL提供了用于多阶段合成的图形体系结构和考虑在程序化和脚本化接口处函数奇偶性的编程模型。API和脚本允许创建在呈现时合成的保留结构或场景描述,还包括具有更多立即模式性质的区域。
通过接口,MIL提供对存储视觉信息的数据结构的访问,因此应用程序可以利用由计算机硬件提供的图形能力。接口支持元素对象模型和向量图形标记语言,后者用使程序代码开发者能够一致地与场景图数据结构接口以产生图形的方式使用元素对象模型。数据结构还可用于直接呈现或“编译”视觉信息,从而可提供给低层图形系统用于快速合成和形成动画。
向量图形元素对象模型主要对应于形状元素和包括与场景图的场景图对象模型联系在一起的图像和视频元素在内的其它元素。标记可分析成包括元素树中元素的数据,元素树被转换成场景图数据结构的对象。其它标记可直接转换成数据和创建场景图对象的调用。标记语言提供不同的方法来描述元素,包括简单的串格式或复杂属性句法,它们可以被命名,能够在标记中的其它位置上重新使用。
MIL的一个方面是通过API集合集成动画和定时,按照固有的基准层概念提供动画。为方便平滑动画,MIL提供了多层图形处理系统和方法(例如,操作系统的)。一个这样的多层图形处理系统包括两个组件,包括请求式运行(tick-on-demand)或慢运行(slow-tick)高层组件和快运行(fast-tick)(例如,以图形硬件帧刷新速度)低层组件。通常,高层较低频率的组件完成更新动画参数及遍历场景数据结构等计算密集的方面,以便将简化的数据结构传递给低层组件。低层组件以较高频率操作,诸如图形子系统的帧刷新率,来将数据结构处理成图形子系统的持续输出数据。低层处理包括在需要时内插任意参数间隔来获得呈现每个动画帧的场景的瞬时值。
顶层MIL对象包括视件树,它是包含要绘制的主要内容的对象。控件将从树的视件直接派生。视件是设备和父亲上下文无关的。呈现目标是对其绘制视件的设备。这个对象(例如屏幕)可有其自己的灰暗或无效机制。各种呈现目标包括窗口中的屏幕、Printer、Metafile、Surface、流媒体文件(例如,DVD)和“Sub-window(子窗口)”,后者是独立于场景其余部分绘制的一部分场景。其它绘制相关的对象包括视件呈现器,它包括配置为绘制视件树到呈现目标上的对象,以及显示调度器对象,它了解何时将视件树绘制到呈现目标上。时间管理器是一组定时节点的上下文对象,而且是调度器调用运行的对象。
提供了Visual API,它实质上是通过媒体集成层绘制的起点,且包括多种类型的对象,包括VisualManager对象,它将视件树连接到媒体。不同类型的VisualManager(例如,Screen、Printer和Surface)负责呈现视件树到它们特定的媒体。视件是程序员进行绘制的地方;它是视件树中的一个节点,并为程序提供绘制的位置。
DrawingContext API提供基于上下文的编程模型,用于如何构造填充Visual或被呈现到ImageData的视件内容。提供DrawingContext类,并且提供获得DrawingContext和枚举RetainedVisual/DrawingVisual中的视件内容所必需的类和入口点。
为支持可变性,提供了从通用Changeable基类派生的一组单独的类型。可变性是需要的变化的任何类型都可从Changeable类派生。例如,在图形编程中,对象模型包括Brush、Pen、Geometry、FloatAnimation、GradientStop、Segment等等。IsChangeable属性规定了changeable对象是否可被修改,取决于其当前值,该值定义了一个状态。
画刷是表示填充平面方法的对象。除了能够以绝对方式填充平面之外,媒体集成层的画刷还能相对于它们要填充的对象尺寸来调整如何填充平面。画刷类型示例包括SolidColorBrush、VisualBrush(它可参照向量图像资源/视件)、DrawingBrush、LinearGradient、RadialGradient、ImageBrush和NineGridBrush。某些画刷对象还有当使用时它们如何相关于坐标系统的概念和它们如何相关于它们所应用于的几何图形边界框的概念。这个尺寸基于画刷所填充的对象。某些类型的画刷(例如VisualBrush)还可平铺来创建程序员定义的模式。Brush基类具有变换、一般不透明性和混合模式。Brush(及向量图形和MIL API中的其它对象资源)对象是Changeable且在创建它们后是可写的,并在合格地使用它们后它们如何行为遵循一般的Changeable模式。
Geometry类的对象可用于用Pen和Brush剪辑、击中测试和呈现基于2D向量基的数据。派生的Geometry类提供更专用的构建和枚举语义。提供了许多形状专用的Geometry类型,以及允许显式定义更复杂形状Ceometry的通用PathGeometry。Geometry是抽象基类。GeometryCollection是多个Geometry对象的集合,这些对象在这些对象的定义区域上使用特定的CombineMode操作被组合起来。这个对象允许比有可能严格地使用PathGeometry中的PathFigure对象更容易地构建Geometry对象的视件组合。
ImageSource是抽象类,包括用于成像的基本构件。ImageSource在概念上表示了某个尺寸和分辨率下单一的、连续的像素集合。例如,ImageSource可以是Decoder提供的图像文件中的单个帧,或者是在某个它自己的ImageSource上操作的变换结果。ImageSource是可改变的,不是因为它自己的属性可以被改变,而是因为其子类的属性有可能被改变。
提供Transform类的对象,用于缩放、旋转、转换和偏斜向量和光栅图形。派生的Transform类友好地提供了用法和枚举语义。
各Effect提供了用以呈现为中心的方式改变场景的视件内容的工具。例如,ImageEffect(基于光栅的位图效果)操作于基于图像的、完全合成的一部分场景的表示。各Effect可分成各种类型,包括ImageEffect、BlendMode和VectorEffect。ImageEffects可通过将它应用于子图或Element在保留模式场景中使用,或者它可在独立图像管道中使用。BlendMode是基于图像效果的特定形式,且可用基本上与ImageEffect相同的方式应用于保留模式场景。混合模式执行源和目的地颜色的组合,因为源是合成的,例如,乘或加。
击中测试用于选取场景中的视件,并且通过从控制树顶部开始并按点或几何图形返回一个控件或一组控件来操作。控件可定义它是否被击中,带有支持服务,包括呈现的几何图形、边界框、带外几何图形(击中区域)、图像不透明性或掩模及其自己的逻辑。控件可在击中时返回特定击中相关的数据。击中测试机制可以用有效方式过滤击中测试结果。击中测试遍历是视件树的深度右至左遍历,带有通过以z顺序、顶至底方式的回调报告的击中。当递降时,击中测试器根据元素层关系例如具有形状的画布或具有内部画布的停放面板来观察过滤。当发生击中时,击中测试器或者可以继续处理更多的击中(如果有的话),或者可以停止。
提供了一种动画系统,由定时控制引擎和一组动画对象组成。定时引擎是一种服务,可由任何展示时变行为的对象例如动画和音频或视频媒体对象使用。动画对象实现一组功能,将时间间隔映射到其它数据类型,它们随后用作较高层对象的输入。图形动画可通过将动画集合与呈现操作相关联来完成。每个用于呈现操作的动画可按独立时钟运行,称为所谓的“时间线(timeline)”。可将多个时间线组织在定时树中来支持分层的定时。一旦绘制了动画的图元并指定了动画参数,低层呈现系统就负责以规则的间隔重新绘制场景。每次呈现一帧时,根据流逝的时间(在大多数情况下由系统时钟测量的),计算在场景中涉及的动画的当前值,随后重新绘制动画的图元。
通过MIL还提供了各种图元类型、颜色特征和媒体支持。MediaData可用于播放任何音频/视频内容。
其它好处和优点通过下面结合附图的详细描述而变得显而易见,其中:
附图说明
图1是方框图,表示可将本发明结合在内的一示例性计算机系统;
图2是方框图,主要表示可以将本发明结合在内的图形层体系结构;
图3示出按照本发明的一个方面的视件的场景图和相关组件,后者用于处理场景图,诸如通过遍历场景图来提供图形命令和其它数据;
图4示出按照本发明的一个方面构造的确认视件、绘制视件和相关联的指令表的场景图;
图5示出按照本发明的一个方面的对象模型的视件类;
图6示出按照本发明的一个方面的对象模型的各种其它对象;
图7示出按照本发明的一个方面的变换类层次结构;
图8和9示出按照本发明的一个方面,视件数据分别在几何图形缩放和非均匀缩放中的变换;
图10示出按照本发明的一个方面的对象模型的几何图形类;
图11示出按照本发明的一个方面的PathGeometry结构;
图12示出按照本发明的一个方面的视件和指令表的场景图,它们示出由图元产生的示例图形;
图13示出按照本发明的一个方面的对象模型的画刷类;
图14是方框图,主要表示按照本发明的一个方面的changeable体系结构,其中由状态机处理请求以控制类型的可变性;
图15-17是状态图,表示按照本发明的一个方面,属性状态如何控制可变类型的行为;
图18-23是按照本发明的一个方面,在示例场景图中对象的分层表示,示出属性如何控制示例代码的状态转移和克隆行为;
图24示出按照本发明的一个方面,由线性渐变画刷对象中的数据产生的呈现图形;
图25示出按照本发明的一个方面,由径向渐变画刷对象中的数据产生的呈现图形;
图26示出按照本发明的一个方面,由具有各种拉伸值而产生的呈现图形;
图27示出按照本发明的一个方面,由具有各种平铺值产生的呈现图形;
图28示出按照本发明的一个方面呈现的九栅格画刷对象;
图29-40是按照本发明的一个方面在动画中使用的示例时间线的图形表示;
图41示出按照本发明的一个方面,通过三维视件构造的示例三维图像;以及
图42示出按照本发明的一个方面的三维概念,用于提供三维支持。
详细说明
示例性操作环境
图1示出了在其上可实现本发明的合适的计算系统环境100的示例。计算系统环境100只是合适的计算环境的一个示例,而非旨在建议任何对本发明的使用或功能范围的限制。计算环境100既不应解释为具有对示例性操作环境100中所示组件的任意之一或组合的任何依赖性和要求。
本发明可用于众多其它通用或专用计算系统环境或配置。可适合于本发明使用的众所周知的计算系统、环境和/或配置的示例包括,但不限于,个人计算机、服务器计算机、手持或膝上型设备、写字板设备、多处理器系统、基于微处理机系统、机顶盒、可编程消费电子产品、网络PC、小型计算机、大型计算机、包括任何上述系统或设备的分布式计算环境等。
本发明可在由计算机执行的计算机可执行指令如程序模块的一般环境中描述。通常,程序模块包括例程、程序、对象、组件、数据结构等,它们完成特定任务或实现特定抽象数据类型。本发明还可在分布式计算环境中实施,其中任务可由通过通信网络连接的远程处理设备完成。在分布式计算环境中,程序模块可位于本地或远程两者的计算机存储介质中,包括存储器存储设备。
参考图1,实现本发明的示例性系统包括计算机110形式中的通用计算设备。计算机110的组件可包括,但不限于,处理单元120、系统存储器130和连接包括系统存储器在内的各种系统组件到处理单元120的系统总线121。系统总线121可以是若干类型的总线结构之任一,包括存储器总线或存储器控制器、外围设备总线和使用各种总线结构之任一的局部总线。作为示例,而非限制,这种结构包括工业标准结构(ISA)总线、微通道结构(MCA)总线、增强ISA(EISA)总线、视频电子标准协会(VESA)局部总线、加速图形接口(AGP)总线和也称为Mezzanine总线的外围组件互连(PCI)总线。
计算机110一般包括各种计算机可读介质。计算机可读介质可以是任何可由计算机110存取的可用介质,并包括易失性和非易失性、可移动和不可移动的介质。作为示例而非限制,计算机可读介质可包括计算机存储介质和通信介质。计算机存储介质包括以任何用于存储诸如计算机可读指令、数据结构、程序模块或其它数据的信息的方法或技术实现的易失性和非易失性、可移动和不可移动的介质。计算机存储介质包括,但不限于,RAM、ROM、EEPROM、闪存或其它存储器技术、CD-ROM、数字多功能盘(DVD)或其它光盘存储器、磁带盒、磁带、磁盘存储器或其它磁存储设备,或者任何可用来存储所想要的信息并能由计算机110存取的其它介质。通信介质一般包含在诸如载波或其它传输机制的调制数据信号中的计算机可读指令、数据结构、程序模块或其它数据,并包括任意信息传输介质。术语“调制数据信号”意指使得以编码信号中信息的方法设置或改变其一个或多个特征的信号。作为示例,但非限制,通信介质包括有线介质,诸如有线网络或直接线连接,和无线介质,诸如声波、RF、红外线和其它无线介质。上述任意的组合也应包括在计算机可读介质的范围内。
系统存储器130包括易失性和/或非易失性存储器形式的计算机存储介质,诸如只读存储器(ROM)131和随机存取存储器(RAM)132。基本输入/输出系统133(BIOS),包含帮助在计算机110内的元件间传送信息的基本例程,诸如在起动期间,一般存储在ROM131中。RAM132一般包含由处理单元120可立即访问和/或现在正操作的数据和/或程序模块。作为示例,而非限制,图1示出操作系统134、应用程序135、其它程序模块136和程序数据137。
计算机110还可包括其它可移动/不可移动、易失性/非易失性计算机存储介质。仅作为示例,图1示出读写不可移动、非易失性的磁介质的硬盘驱动器141、读写可移动、非易失性的磁盘152的磁盘驱动器151和读写诸如CD ROM或其它光介质的可移动、非易失性的光盘156的光盘驱动器155。其它可用于示例性操作环境的可移动/不可移动、易失性/非易失性计算机存储介质包括,但不限于,磁带盒、闪存卡、数字多功能盘、数字视频带、固态RAM、固态ROM等。硬盘驱动器141一般通过诸如接口140的不可移动存储接口连接到系统总线121,而磁盘驱动器151和光盘驱动器155一般由诸如接口150的可移动存储器接口连接到系统总线121。
以上讨论并示于图1的驱动器及其相关的计算机存储介质为计算机110提供了计算机可读指令、数据结构、程序模块和其它数据的存储。在图1中,例如,硬盘驱动器141被示为存储操作系统144、应用程序145、其它程序模块146和程序数据147。注意这些组件可以相同也可以不同于操作系统134、应用程序135、其它程序模块136和程序数据137。操作系统144、应用程序145、其它程序模块146和程序数据147在这里给出不同数字以示出它们至少是不同的拷贝。用户可通过诸如写字板(电子数字化转换器)164、话筒163、键盘162和通常称为鼠标、轨迹球或触摸板的定点设备161的输入设备将命令和信息输入到计算机110中。其它输入设备(未示出)可包括游戏操纵杆、游戏垫、卫星天线、扫描仪等。这些和其它输入设备常常通过耦合到系统总线的用户输入接口160连接到处理单元120上,但也可通过其它接口和总线结构连接,诸如并行端口、游戏端口或通用串行总线(USB)。监视器191或其它类型的显示设备也通过诸如视频接口190的接口连接到系统总线121上。监视器191还可与触摸屏面板193等集成在一起,能够通过诸如触摸屏接口192的接口输入诸如手写内容的数字化输入到计算机系统110中。注意监视器和/或触摸屏面板可物理地耦合在其中结合了计算设备110的机架上,诸如写字板类型的个人计算机,其中触摸屏面板193实质上用作写字板164。另外,诸如计算设备110的计算机还可包括其它外围输出设备,诸如扬声器195和打印机196,它们可通过输出外围设备接口194等连接。
计算机110可运行在使用逻辑连接到一或多台诸如远程计算机180的远程计算机上的网络化环境中。远程计算机180可以是个人计算机、服务器、路由器、网络PC、对等设备或其它普通网络节点,且一般包括许多或所有上面相对于计算机110所述的元件,尽管只有存储器存储设备181示于图1。绘于图1的逻辑连接包括局域网(LAN)171和广域网(WAN)173,但还可包括其它网络。这样的网络化环境在办公室、企业级计算机网络、内联网和因特网中都很普通。
当在LAN网络环境中使用时,计算机110通过网络接口或适配器170连接到LAN171上。当在WAN网络环境中使用时,计算机110一般包括调制解调器172或其它在诸如因特网的WAN173上建立通信的装置。调制解调器172,它可以是内置或外置的,可通过用户输入接口160或其它合适的机制连接到系统总线121上。在网络化环境中,相关于计算机110所述的程序模块或其部分可存储在远程存储器设备中。作为示例,而非限制,图1示出了远程应用程序185,驻留在存储器设备181上。要意识到所示网络连接都是示例性的,并可使用其它在计算机间建立通信连接的装置。
媒体集成层(MIL)
本发明的一个方面主要针对称为媒体集成层(MIL)的体系结构,它包括立即模式图形应用编程接口(API)、在高速缓存绘图指令中也扮演角色的屏幕划分数据结构和API、一组控件层对象以及一种标记语言。一般而言,该体系结构允许诸如应用程序或操作系统组件的程序代码传送绘图指令和其它信息(例如,图像位图)到图形组件,以便在系统显示器上呈现图形输出。本发明的一个方面提供了许多已定义的函数和方法,例如,以API到对象模型的形式,它们能使程序用数据结构、指令表(绘图图元/命令)和其它图形相关数据来填充场景图。当被处理时,场景图产生显示在屏幕上的图形。
按照本发明的一个方面,MIL是在层中工作的合成系统。被合成的每一项都在概念上被绘制到具有完整alpha信道(alpha channel)的位图中。然后在将该位图合成到后缓冲区(back buffer)时使用alpha信道。从后到前合成各个对象。注意尽管这是概念模型,实际上,系统理解什么时候不需要完整的中间位图表面并直接合成到后缓冲区或其它后表面(backing surface)。系统还能理解递增变化并进行最小的重画。
图2表示可在其中实现本发明的一般分层体系结构(MIL)200。如图2所示,可开发程序代码202(例如,应用程序或操作系统组件等)以一或多种不同的方法,包括通过成像(imaging)204、通过向量图形元素206和/或通过直接对视件应用程序编程接口(API)层212设置的函数/方法调用,来输出图形数据。通常,成像204为程序代码202提供加载、编辑和保存图像(例如位图)的机制。如下所述,这些图像可由系统的其它部分使用,并且还有一种方法使用图元绘制代码来直接绘制图像。向量图形元素206提供另一种方法来绘制图形,与其余的对象模型一致(下面描述)。向量图形元素206可通过标记语言创建,元素/属性系统208和布局系统210将它解释为对视件API层212进行合适的调用。向量图形元素206,连同元素/属性系统208和布局系统210在前面提到的共同待批的专利申请序列号10/401,717中描述。
这样,MIL200包括程序员可对其编程的不同层,包括成像204,它是用于加载、编辑和保存图像的管道。这些图像可在需要时用于系统的其余部分。而且,有一种方法使用图元绘制代码直接绘制成图像。
另一层包括Visual API 212,它是一个主要为组织要绘制的项提供对数据结构216的访问的API。这些项的每一个都能与可由系统高速缓存的绘制指令一起加载。存在各种各样的方法来指定这个数据结构及所要绘制的内容;在典型的了解MIL的应用程序内部,可从布局系统210内使用这个API。
编程的第三层包括向量图形元素层206,它是一种标记语言,以与其余部分的控件/元素对象模型一致的方式描述和绘制图形。向量图形元素通过元素系统揭示图形系统。这包括一组用于呈现的元素和一组在任意元素上工作的属性。在一种实现中,存在两个子集,包括元素层向量图形和资源层向量图形,前者被分析成元素并创建元素,后者被分析并以有效方式存储。元素层对象模型指在较高层控件世界的操作,它引进了元素树、属性系统和布局系统210。至于分析,元素层上的许多动态属性是MIL类型的。通常,标记被分解成对象,其中通常在标记文件的顶部如下说明用于XAML标记的XML大纲:
<Canvas xmlns=″http://schemas.microsoft.com/2003/xaml″
xmlns:def=″Definition″
def:Class=″Surfin.ChannelBrowser″
def:CodeBehind=″ChannelBrowser.xaml.cs″
ID=″mainCanvas″Background=″Black″Width=″100%″Height=″100%″
Loaded=″PageLoaded″>
例如,当使用<Path>标记时,分析程序用该大纲来查找有关的名字空间(例如,System.Windows.Shapes)来分解和构建对象。如前面提到的共同待批的专利申请序列号10/401,717中主要描述的,分析程序依赖于类型转换程序来将一个串转换成MIL对象的实例。这些需要复杂句法的类型具有揭示为可选XML属性的每个可写的CLR(公共语言运时间)属性,它是用与动态属性同样的方式分析的。一些类型(特别是Brush)可以用简单或者复杂形式分析。
应该注意针对任意这些层或任意这些类的函数调用可直接或间接处理。例如,请求处理程序可包括中间件代码,它将在一个操作系统中接收的请求转换成由另一操作系统处理的API调用。这样,如在这里所使用的,函数由“引起”所请求行为发生的程序调用,而忽略实际处理在哪里发生或在哪里提供数据结构和类。
正如将要理解的以及也表示在图2中的,动画系统220遍及整个API。如这里所描述的,动画值实质上可传递到任意地方,包括在元素属性层208、在Visual API 212内部和在任意其它资源中。还在元素和视件层两者上揭示定时系统(timing system)。
在一个实施例中,图形层体系结构200包括高层合成和动画引擎214,它包括或者关联于高速缓存数据结构216。高速缓存数据结构216包含场景图(scene graph),它包括按照已定义的对象模型管理的分层排列对象,如下所述。通常,Visual API层212为程序代码202(和布局系统210)提供到高速缓存数据结构216的接口,包括创建对象、打开和关闭对象的能力来给它们提供数据等等。换句话说,高层合成和动画引擎214揭示一个统一的媒体API层212,通过这个层开发者可表达有关显示图形信息的图形和媒体的意图,并且为基础平台提供足够的信息,使得该平台可以优化程序代码对硬件的使用。例如,基础平台负责高速缓存、资源协商和媒体集成。
在一个实施例中,高层合成和动画引擎214将指令流和可能的其它数据(例如,指向位图的指针)传递到快速的低层合成和动画引擎218。通常,低层合成和动画引擎/呈现程序218提供一组系统来管理实际绘制与合成到屏幕上。注意如这里所使用的,术语“高层(high-level)”和“低层(low-level)”与在其它计算情景中使用它们相似,其中一般而言,软件组件相对于较高组件越低,该组件就越接近于硬件。这样,例如,从高层合成和动画引擎214发送的图形信息可在低层合成和动画引擎218接收,其中信息用于将图形数据送到包括硬件222在内的图形子系统。注意本发明可扩展到两层以上的多层合成。
而且,注意为了促进分辨率和设备无关的用户界面,像素的概念不揭示为主API中的基本单位。代之以设置初始坐标系统,因此坐标系统中的一个单位等于1/96英寸。这可称为dip,或者px,即使在一些系统(诸如高分辨率监视器或打印机)上它不映射到像素。在长度方向上,dip单位直接转换为一个用户单位。其它物理单位(in、cm、pt等)之间的乘数锁定在1/96英寸。这意味着如果使用缩放变换,它将影响所绘制的一切,即使它是物理上指定的。选择了1/96英寸的值,因此一个默认用户单位等于默认设置的当代显示器上的像素。注意可提供一种机制来给布局系统和其它用户代码提供提示,从而它们可优化它们所呈现于的设备的输出分辨率。
高层合成和动画引擎214结合程序代码202一起构建场景图来表示由程序代码202提供的图形场景。例如,要绘制的每个项可与绘制指令一起加载,系统可将它高速缓存在场景图数据结构216中。如下面所要描述的,存在许多不同的方法指定数据结构216及所绘制的内容。而且,高层合成和动画引擎214集成了定时和动画系统220来提供说明的(或其它)动画控件(例如,动画间隔)和定时控件。注意动画系统实质上允许动画值传递到系统中的任意地方,包括,例如,在元素属性层208、在Visual API层212内以及在任何其它资源中。在元素和视件层上揭示定时系统。
低层合成和动画引擎218管理场景的合成、动画和呈现,然后提供给图形子系统222。低层引擎218合成用于多线程场景的呈现(例如,来自一或多个应用程序),且用呈现组件实现图形到屏幕的实际呈现。但是,注意,有时对于发生在较高层的一些呈现它可能是必需和/或有利的。例如,尽管较低层服务请求来自多线程,但较高层在每线程基础上实例化,从而有可能通过成像机制204在较高层上执行时间消耗或线程专用的呈现,并将对位图的引用传递给较低层。
MIL200提供了许多概念,它们集成起来提供在图形和音视频编程方面的改进,诸如一组可通过整个分层堆栈共享的资源和类,包括Pen、Brush、Geometry、Transform和Effect。而且,提供简单的图元类型,包括Point、Rectangle等。Pen和Brush是复杂类型,描述了如何影响在这些不同层上的呈现。还提供的是一种特殊类型的Brush,称为VisualBrush,它允许程序员使用任意图形“元文件(metafile)”来填充一个区域(显式地通过VisualBrush或者通过引用VisualBrush的Pen)。由于这是用于存储和使用任意图形的压缩形式,因此它扮演图形资源的角色。存在一种用来直接创建这些对象的向量图形标记句法的特定简档(profile)。尽管大体上类似于VisualBrush,但DrawingBrush更压缩和摘要化,并且实质上是一个元文件画刷,而VisualBrush是场景图画刷。
其它类包括Geometry,它是一个复杂类型,用来定义用于填充、笔划或剪辑的区域。Transform是另一种复杂类型层次,用于定义如何变换坐标空间。Effect描述一种系统,用于将任意过滤效果(例如模糊)放在一部分内容上。注意这还包括插件可扩展性模型。
提供一种Visual API,它使用以上类型取得到屏幕或其它目标的二进制位。这包括到系统其余部分的基层挂钩(base level hookup)(通过hWnd或其它机制),连同上面引入的屏幕划分数据结构。成像允许程序员将图象放入基于MIL的系统或者从中取出。媒体提供使用其它形式媒体(包括音频和视频)的能力。通常,Visual API指这样的API集合,它在元素系统和布局系统之下操作,并且指直接用Visual或对Visual进行编程,而不是在更高层上编程。注意visual是高速缓存数据结构216中的基本对象,它包括屏幕上可视物的保留数据结构(retained data structure),并且还为性能的原因而高速缓存指令表(Instruction List)和设备专用的资源。
图3和4分别示出示例场景图300和400,包括称为Visual的基对象。通常,Visual包括一个对象,它向用户表示一个可视表面并具有在显示器上的Visual表示。如图5所示的,基类Visual为其它Visual类型提供基准功能,即Visual类是一个抽象基类,从它可派生各种Visual类型。
如图3所示,顶层(或根)Visual 302连接到Visual管理器对象304上,它还具有与窗口(hWnd)306或相似单元的关系(例如通过句柄),在其中为程序代码输出图形数据。VisualManager 304管理将顶层Visual(及该Visual的子对象)绘制到那个窗口306。图6示出VisualManager作为在这里所述的图形系统中的对象模型中的一组其它对象620中的一个。
为了绘制,VisualManager 304按分配器(dispatcher)308所调度的处理(例如遍历或者传输)场景图,并且提供图形指令和其它数据给其相应窗口306的低层组件218(图2),诸如在上述美国专利申请中主要描述的。场景图处理通常由分配器308以比低层组件218和/或图形子系统222的刷新速度相对较慢的速度来调度。图3示出许多在顶层(根)Visual 302之下分层地安排的子Visual 310-314,其中一些表示为已经分别通过绘制上下文316、317(示为虚线框来表示它们的临时性质)用相关的指令表318和319填充了,例如包含Instruction List(指令表)和其它Visual。Visual还包含其它属性信息。一般而言,在基视件类上的大多数访问是经IVisual接口而来的,并且视件是从DependencyObject派生的,如图5所示。Visual(在附录中进一步描述)还可包含其它属性信息,如在下面的示例Visual类中所示:
  public class Visual:IVisual,DependencyObject
  {
    protected Visual();
    protected Visual(UIContext context);
    bool IVisual.HasChildren{get;}
    VisualCollection IVisual.Children{get;}
    Visual IVisual.Parent{get;}
    Geometry IVisual.Clip{get;set;}
    Bool IVisual.Show{get;set;}
    double IVisual.Opacity{get;set;}
    BlendMode IVisual.BlendMode{get;set;}
Matrix IVisual.TransformToAncestor(Visual ancestor);
Matrix IVisual.TransformToDescendant(Visual descendant);
Matrix IVisual.TransformFromAncestor(Visual ancestor);
Matrix IVisual.TransformFromDescendant(Visual descendant);
Matrix IVisual.TransformToVisual(Visual visual);
Matrix IVisual.TransformFromVisual(Visual visual);
bool IVisual.IsAncestorOf(Visual descendant);
bool IVisual.IsDescendantOf(Visual ancestor);
Visual IVisual.FindCommonVisualAncestor(Visual otherVisual);
PointHitTestResult IVisual.HitTest(Point point);
void IVisual.HitTest(
   HitTestFilterDelegate filterHitDelegate,
   HitTestResultDelegate resultHitDelegate,
   HitTestParameters hitTestParams);
   Rect IVisual.VisualContentBounds{get;}
   Rect IVisual.VisualDescendantBounds{get;}
   protected virtual PointHitTestResult HitTestCore(
      PointHitTestParameters point);
   protected virtual GeometryHitTestResult HitTestCore(
      GeometryHitTestParameters geometry);
   protected virtual Rect HitTestBounds{get;}
}
Visual是图形内容和一组子对象的容器。在Visual上的各种属性可以用于控制Visual的呈现行为。例如通过在Visual上设置剪辑,Visual的内容被剪辑成指定的形状。其它属性为变换、混合模式、不透明性、显示等。所有这些属性可通过取(get)和设置(set)属性来控制。
Show属性用于显示/隐藏视件,例如,当false时视件是不可见的,否则视件是可见的。而且,MIL对象(无论是在Visual API层的Visual还是元素层上的元素)存在于层次结构中。坐标系统是通过这个层次结构继承下来的。这样,父亲对象可以使坐标变换进栈,后者修改呈现遍(rendering pass)并且获得应用于该父亲的子对象。
视件的变换是在到该视件的连接上。换句话说,在父亲的VisualCollection Children属性上通过[Get|Set]ChildTransform来设置它。也参见稍后描述的VisualCollection。
注意坐标变换可用统一的方法应用于一切,就好象它在位图中。注意这并不意味着变换总是应用于位图,而是获得呈现的内容是被变换同等影响的。作为示例,如果用户用一英寸宽的圆笔划一个圆,然后对那个圆应用X方向上两倍于它的缩放,则笔将是在左右上两英寸宽而上下只是一英寸宽。这有时称为合成或位图变换(与只影响几何图形的的骨架或几何图形缩放相反)。图8示出缩放变换,其中出现在左边的是未变换图像800,出现在右边的是具有非均匀缩放的变换图像802。图9示出缩放变换,其中出现在左边的是未变换图像800,出现在右边的是具有几何图形缩放的变换图像904。
关于视件的坐标变换,TransformToDescendant返回一种变换,它反映从引用视件到子孙视件的坐标空间改变。该变换然后可用于,例如将一个点从引用视件的坐标空间变换到子孙视件的坐标空间。TransformFromDescendant相似地返回一个变换,它描述从子孙Visual到引用Visual的坐标空间改变。该变换然后可用于将一个点从子孙视件的坐标空间变换到引用视件的坐标空间。为了方便,Visual API还提供TransformToAncestor、TransformFromAncestor、TransformFromVisual和TransformToVisual,它们也返回相应坐标空间改变的变换。注意在后两个API中,未指定Visual之间的关系。它们甚至可以是Visual树中的对等对象,只要它们共享一个共同的祖先。该实现将找到该共同祖先,然后计算从引用Visual到共同祖先的坐标变换,再计算从共同祖先到目标Visual的坐标变换。所得到的变换可用于例如在指定Visual之间变换一个点。
两个取(get)属性可用,用于确定Visual内容的边界框,即VisualDescendantBounds和VisualContentBounds,前者是所有子孙对象的图形内容的边界框,后者是内容的边界。对它们应用Union可提供Visual的总边界。
剪辑属性设置(或取)视件的剪辑区域。任何Geometry(图10示出几何图形类并且在下面的Geometry章节中描述的)可以用作剪辑区域。在一个实现中,剪辑区域的默认设置是0,即没有剪辑,可以认为它是从(-∞,-∞)到(+∞,+∞)的无限大剪辑矩形。
Opatity属性取/设置视件的不透明性值,使得根据不透明性值和所选的混合模式将视件的内容混合在绘制表面上。BlendMode属性可以用于设置(或取)所使用的混合模式。例如,在混合模式设置为线性alpha混合的情况下,可以在0.0与1.0之间设置不透明性(alpha)值,例如,Color=alpha*前景色+(1.0-alpha)*背景色。在视件中可包括其它服务,诸如特殊效果属性,例如,模糊,单色等等。
Visual还有Children属性,用于管理子集合。它还提供HasChildren属性来检查Visual是否有子。Children属性返回VisualCollection,它让用户在子集合上执行象添加、移除、插入等操作。以下示出VisualCollection的
例子:
  public class Visual:ICollection,IEnumerable
  {
       public Int32 Add(Visual visual)
       public Void Clear()
       public Boolean Contains(visual visual)
       public virtual sealed Void CopyTo(Array array,Int32 index)
       public Int32 get_Capacity()
       public virtual sealed Int32 get_Count()
       public virtual sealed Boolean get_IsSynchronized()
       public Visual get_Item(Int32 index)
       public virtual sealed Object get_SyncRoot()
       public virtual sealed IEnumerator GetEnumerator()
       public Transform GetTransform(Int32 index)
       public Transform GetTransform(Visual child)
       public Int32 IndexOf(Visual visual)
       public Void Insert(Int32 index,Visual visual)
       public Void Remove(Visual visual)
       public Void RemoveAt(Int32 index)
       public Void RemoveRange(Int32 index,Int32 count)
       public Void set_Capacity(Int32 value)
       public Void set_Item(Int32 index,Visual value)
       public Void SetTransform(Int32 index,Transform transform)
       public Void SetTransform(Visual child,Transform transform)
      public Void TrimToSize()
   }
在VisualCollection中Visual的顺序决定呈现这些Visual的顺序,即从最低的索引到最高的索引从后向前(绘画顺序)呈现Visual。
ProxyVisual是一种可不止一次添加到场景图中的视件,例如,在容器视件之下。由于任何由ProxyVisual引用的视件可通过从根起的多个路径到达,因此读服务(TransformToDescendant,TransformFromDescendant和HitTest)不通过ProxyVisual工作。实际上,存在一条从任何视件到视件树根的规范路径且该路径不包括任何ProxyVisual。
图4示出示例场景图400,其中在场景图中ContainerVisual和DrawingVisual是相关的,并且具有指令表形式的相关数据(例如在相应的绘制上下文中)。ContainerVisual是从Visual基类派生的只有结构内容的Visual。Visual可以彼此任意嵌套。特别是嵌套ContainerVisual是合法的。ContainerVisual的主要目的是为Visual提供容器,能够方便地访问它们而不用通过IVisual接口。ContainerVisual因此再次将所有IVisual方法重新实现为公有方法。ContainerVisual的子可以用ContainerVisual的VisualCollection Children属性上的方法来操作。
回到图5,还有一个视件是HwndVisual 505,它定位场景图中的Win32子hWnd。更特别地,传统程序仍将通过WM_PAINT方法(等)操作,该方法基于以前的图形技术绘制到子hWnd(等)。为在新图形处理模型中支持这样的程序,在贮存了父亲视件时,HwndVisual允许在场景图中包含hWnd并移动它。其它类型的视件506也是可行的,诸如三维(3D)视件,它支持两维与三维世界之间的连接,例如,类似照相机的视图有可能通过两维视件获得到三维世界中的视图。下面描述这样的3D视件。
如上所述,可以通过用各种绘制图元(包括Geometry、ImageSource和MediaData)填充视件的绘制上下文来绘制视件。而且,存在一组通过这整个堆栈共享的资源和类。这包括Pen、Brush、Geometry、Transform和Effect。DrawingContext抽象类揭示一组绘制和上下文状态操作,可用于填充DrawingVisual、RetainedVisual、ImageData等。换言之,绘制上下文抽象类揭示一组绘制操作和进栈/出栈操作:对于每个绘制和进栈操作存在两种方法,一是用常量作为变元,一是将动画绘制对象(animator)作为变元。进栈/出栈操作的例子是PushTransform、PopTransform、PushClip、PopClip、PushOpacity、PopOpacity等。
可以在绘制上下文上使各种服务(包括变换、不透明性和剪辑)进栈和出栈,并且可以嵌套进栈/出栈操作,只要每个进栈调用有一个适当的出栈调用。
PushTransform方法使变换进栈。相对于进栈的变换,执行后续的绘制操作。出栈调用使变换(由匹配的PushTransform调用使其进栈的)出栈:
void PushTransform(Transform transform);
void PushTransform(Matrix matrix);
void Pop();。
同样,PushOpacity方法使不透明性值进栈。用指定的不透明性值在临时表面上呈现后续的绘制操作且随后合成到场景中。Pop()使不透明性(由匹配的PushOpacity调用使其进栈的)出栈:
void PushOpacity(float opacity);
void PushOpacity(FloatAnimation opacity);
void Pop();。
PushClip方法使剪辑的几何图形进栈。后续的绘制操作被剪辑成几何图形。在后变换空间中应用剪辑。Pop()使剪辑区域(由匹配的PushClip调用使其进栈的)出栈:
void PushClip(Geometry clip);
void Pop();。
注意,可以任意嵌套进栈操作,只要出栈操作与进栈匹配。例如,下面是有效的:
  PushTransform(...);
  DrawLine(...);
  PushClip(...);
  DrawLine(...);
  Pop();
  PushTransform(...);
  DrawRect(...);
  Pop();
  Pop();
Geometry是一种类(图10),它定义向量图形骨架,没有笔划或填充。每个几何图形对象是简单形状(LineGeometry、EllipseGeometry、RectangleGeometry)、复杂的单一形状(PathGeometry)或通过指定的组合操作(例如,并、交等)形成的这类形状的列表GeometryCollection。这些对象形成如图10所示的类层次结构。
如图11所示,PathGeometry是Figure对象的集合。每个Figure对象依次由一或多个Segment对象组成,它们实际上定义了外形(figure)的形状。Figure是Geometry的子部分,它定义线段(segment)集合。这个线段集合单一连接的一系列两维Segment对象。Figure可以是具有确定面积的封闭形状,或者只是连接的一系列Segment,定义了一条曲线但没有包围的面积。
如图12所示,当绘制几何图形(例如矩形)时,可以指定画刷或笔,如下所述。而且,笔对象还具有画刷对象。画刷对象定义如何以图形方式填充平面,并且存在画刷对象的类层次结构。这在图12中由被填充的矩形1202来表示,它是在包括矩形和画刷指令和参数的视件被处理时产生的。Pen对象保持Brush,连同Thickness、LineJoin、LineCap、EndCap、MiterLimit、DashArray和DashOffset属性,如下所述。也如下所述,一些类型的Brush(诸如渐变(gradient)和九栅格(nine grid))自己确定尺寸。在使用时,这些画刷的尺寸是从边界框获得的,例如,当Brush的GradientUnits/DestinationUnits设置为RelativeToBoundingBox时,使用正在绘制的图元的边界框。如果这些属性设置为Absolute,则使用坐标空间。
如上面提到并且下面将进一步描述的,本发明的图形对象模型包括Brush对象模型,它通常针对用像素覆盖平面的概念。在图13的层次结构中示出画刷类型的例子,并且在Brush基类之下,包括GradientBrush、NineGridBrush、SolidColorBrush和TileBrush。GradientBrush包括LinearGradient和RadialGradient对象。从TileBrush派生出DrawingBrush和ImageBrush。这些类的替换安排是可行的,例如,从TileBrush派生出的可以是ImageBrush、VisualBrush、VideoBrush、NineGridBrush和DrawingBrush。注意,Brush对象可在使用它们时识别它们是如何与坐标系统相关的,和/或它们如何与在其上使用它们的形状的边界框相关的。通常,可从画刷在其上绘制的对象推断出诸如尺寸之类的信息。更具体地,许多画刷类型使用坐标系统来指定其某些参数。这个坐标系统可以相对于应用画刷的形状的简单边界框来定义,或者可以相对于在使用画刷时活动的坐标空间来定义。它们分别称为RelativeToBoundingBox和Absolute模式。
Visual API
Visual API是通过媒体集成层绘制的起点,并且包括多种类型的对象,包括VisualManager对象,它将Visual Tree(视件树)连接到媒体。不同类型的VisualManager(例如,Screen、Printer、Surface)管理将视件树向它们的特定媒体呈现的过程。在本文标题为“顶层MIL对象”的章节中进一步描述VisualManager。
视件是用户进行绘制的地方。它是视件树(一种容器对象,为场景的结构,如下所述)中的节点,并为程序提供绘制的地方。存在各种类型的视件,各自适用于不同的用途。视件与Win32 hWnd的视件/输出侧相似。
视件提供许多能力,包括父亲视件访问,子视件集合,基于任意几何图形的剪辑,不透明性,混合模式,影响该视件其子对象的变换,击中测试,坐标变换服务,边界框服务和效果(光栅和向量)。
为呈现视件场景,遍历视件树,例如,上-下,左-右,首先呈现内容,然后从左至右遍历Visual的子对象。在绘制视件本身内容之前,先绘制该视件的任何子对象。如果内容需要回调给用户,则在呈现时同步地发生。这里是一些伪代码,用于系统在将Visual树呈现给设备时所做的事情(通过VisualRender)。
    Visual.RenderToDeviee(device)
    {
      this.RenderContents(device);
      foreach(Visual child in this.Children)
      {
      Child.Walk(ctx);
     }
   }
在RenderContents调用期间,派生的视件可回调给用户。
图13表示在一个实现中的视件类层次结构。在作为呈现遍部分发生的回调期间,(包括回调给IRetainedVisual.Render或回调给PaintingVisual.RenderCore)Visual树因性能原因而被“锁定”。这种锁定在上下文级基础上发生,意味着在锁定时没有上下文能修改树,无论视件属于哪一视件树。当树被锁定时,Visual的子Visual不能被改变,并且无论用什么方法(例如,打开,设置根3D模型等)都不能改变另一视件的内容,不能在Visual上设置Transform、Opacity、Clip或Effect,不能进行击中测试,也不能进行Get(取)边界信息操作。
通过IVisual接口揭示在Visual上的能力,从而使这些能力公有,同时保护了对象模型。下面是在一个示例实现中的IVisual接口。
  public interface IVisual
  {
       bool HasChildren{get;}
       VisualCollection Children{get;}
       Visual Parent{get;}
       Geometry Clip{get;set;}
       bool Show{get;set;}
       double Opacity{get;set;}
       Matrix TransformToAncestor(Visual ancestor);
       Matrix TransformToDescendant(Visual descendant);
       Matrix TransformFromAncestor(Visual ancestor);
       Matrix TransformFromDescendant(Visual descendant);
       Matrix TransformToVisual(Visual visual);
       Matrix TransformFromVisual(Visual visual);
       bool IsAncestorOf(Visual descendant);
       bool IsDescendantOf(Visual ancestor);
       Visual FindCommonVisualAncestor(Visual otherVisual);
      PointHitTestResult HitTest(Point point);
      void HitTest(
        HitTestFilterDelegate filterHitDelegate,
        HitTestResultDelegate resultHitDelegate,
        HitTestParameters hitTestParams);
      Rect VisualContentBounds{get;}
      Rect VisualDescendantBounds{get;}
   }
Visual包括呈现内容和子对象的集合。许多属性,包括变换、剪辑、不透明性、混合模式等可以用于控制Visual树的实际呈现。注意,Visual不必同时具有内容和子对象。在一个实现中,呈现内容和子集合可以在请求时创建以优化存储器使用。Visual API允许它的用户从Visual派生并使它专用化。
在子对象上的变换是通过在VisualCollection类型的属性Children上的变换来完成的。
public Void SetChildTransform(Visual visual,Transform transform);
public Transform GetChildTransform(Visual visual);
Transformation Read Services提供一个方法,它允许用户获得一个Matrix,该Matrix表示从一个坐标帧到另一个的聚集变换:
Matrix TransformToDescendant(Visual descendant);
Matrix TransformFromDescendant(Visual descendant);
Matrix TransformToAncestor(Visual ancestor);
Matrix TransformFromAncestor(Visual ancestor);
Matrix TransformToVisual(Visual visual);
Matrix TransformFromVisual(Visual visual);
TransformToAncestor和TransformToDescendant更有效,但要求调用者知道两个Visual之间的关系。更一般的TransformToVisual/TransformFromVisual方法找出共同的祖先对象并计算到该视件的变换。注意,这些可引起高速缓存被更新,并引起在任意视件上的OnRender被调用。如果没有连接视件或者遇到退化的变换,则抛出异常。
还提供边界计算:
protected Rect VisualDescendantBounds{get;}
protected Rect VisualContentBounds{get;}
VisualDescendantBounds返回当前视件的子孙对象的内容边界框的合并,但不包括当前视件的内容。VisualContentBounds返回当前视件的内容的边界框。
Opacity属性(例如,双精度型)指定一个可选的Opacity值,在组合到Visual的父亲对象时应用于该Visual。默认地,该值为1.0,它使内容以其完全Opacity出现。注意,由于该值乘以在子图中的任何其它Opacity数据,因此1.0的Opacity什么也不改变。0.0的Opacity使整个内容是透明的,0.25的值使Opacity为其名义值的百分之二十五,等等。在应用BlendMode之前应用Opacity。
BlendMode是指定可选的BlendMode的属性,当Visual被合成时,它应用于子图的内容和目的地。默认地,这个值是BlendMode.Normal,它执行alpha信道了解的合成(Alpha-channel aware composition)到目的地中。将这个属性设置成某个其它值将执行将Visual的内容作为源且呈现目标内容作为目的地的组合。在应用Opacity属性之后应用它。
基视件类提供Visual共有特征的接口:
public class System.Windows.Media.Visuals.Visual:
 DependencyObject,IVisual
{
 //构造函数
 protected Visual();
 protected Visual(UiContext Context);
 //析构函数
 ~Visual();
 protected virtual PointHitTestResult HitTestCore(
  PointHitTestParameters point);
 protected virtual GeometryHitTestResult HitTestCore(
  GeometryHitTestParameters geometry);
 protected virtual Rect HitTestBounds{get;}
 //实现IVisual的所有方法。
 //仅为该接口显式地实现它们。这是一个例子:
 bool IVisual.HasChildren{get;}
}
ContainerVisual直接从视件类派生并将受保护的各属性提升为public(公有)。这使用户能够创建视件容器关系而不必派生新类。
public class System.Windows.Media.Visuals.ContainerVisual:Visual
{
 //构造函数
 public Visual();
 public Visual(UiContext Context);
 //所有IVisual方法被“重新揭示”,因此它们是public的。
 //本类仅是Visual之上和之外的一个便利
}
RetainedVisual是引入可以用于绘制的“保留的指令流”的视件:
public class System.Windows.Media.Visuals.RetainedVisual:Visual
{
 protected RetainedVisual();
 protected RetainedVisual(UiContext Context);
 //打开/关闭语义
 protected DrawingContext RenderOpen();
 protected DrawingContext RenderAppend();
 //无效
 protected bool IsVisuallnvalid{get;}
 protected bool InvalidateVisual();
 Rect Rend Bounds{set;get;}
}
public class System.Windows.Media.Visuals.IRetainedRender
{
 void Render(DrawingContext drawingContext);
}
指令流可以在OnDemand模式中使用,其中在必要时用户被回调以呈现。要求用户实现IRetainedRender。该指令流可以在强制模式中使用,其中用户可以直接调用RenderOpen并取得绘制上下文。通常用户将一次使用这些模式中的一个,但有可能以混合方法使用它们。
RenderOpen和RenderAppend将影响当前流并且可在各种场景中使用。如果这个Visual当前正在Render回调中则它们将抛出。RenderOpen清除在RetainedVisual中所有先前的内容,而RenderAppend将新的内容附加在流的最后。如果用户已经在视件上实现了IRetainedRender,则用户将用信号通知系统还应当使用OnDemand模式。系统将用该值设置到RenderBounds属性中作为由Render调用提供的内容边界。当实现IRetainedRender时,系统可决定优化场景并在任何时候抛弃内容。RenderBounds将默认为一个空的rect(矩形),尽管Rect.Infinite或未设置值是可行的选择。为取得隐含在回调中的虚拟化性能增益,用户必须设置一个合理值。
当呈现场景时,系统在概念上将检查每个视件(注意,实际上在大多数情况下系统将会忽略大多数视件)。如果那个视件的IsVisualInvalid设置为真,并且基于RenderBounds,将需要那个视件的内容,然后系统将调用IRetainedVisual.Render来填充那个视件的内容。这将取代已经在那里的任何内容。用户可以手工地通过调用Invalidate告诉系统抛弃内容流。
如果没有实现IRetainedRender,则IsVisualInvalid将始终返回false。Invalidate将什么也不做。注意,IRetainedRender这样命名(例如,代替IRender),因为它一般不足以在所有呈现回调情况中使用。例如,PaintingVisual用无效的矩形来回调。
DrawingVisual与RetainedVisual非常相似,但被设计为在没有派生的情况下使用。protected方法被“提升”为public。而且,没有Render回调或者没有必要实现IRetainedRender。因此,总是保留内容,与在RetainedVisual上没有实现IRetainedRender时相似。
public class System.Windows.Media.Visuals.DrawingVisual:
 ContainerVisual
{
 //构造函数
 public DrawingVisual();
 public DrawingVisual(UiContext Context);
 //树接口
 public bool HasChildren{get;}
 public Visual VisualChildren{get;}
 public bool IsVisualAncestorOf(Visual descendant);
 public bool IsVisualDescendantOf(Visual ancestor);
 public Visual FindCommonVisualAncestor(Visual otherVisual);
 //标准合成属性
 public new Geometry VisualClip{get;set;}
 //默认为1.0
 public new double VisualOpacity{get;set;}
 public new DoubleAnimationCollection VisualOpacityAnimations{get;set;}
 //默认值为BlendMode.Normal
 public new BlendMode VisualBlendMode{get;set;}
 //变换
 public Transform TransformToDescendant(Visual descendant);
 public Transform TransformFromDescendant(Visual descendant);
 public Transform TransformToAncestor(Visual ancestor);
 public Transform TransformFromAncestor(Visual ancestor);
 public Transform TransformToVisual(Visual visual);
 public Transform TransformFromVisual(Visual visual);
 //边界计算
 public new Rect VisualDescendantBounds{get;}
 public new Rect VisualContentBounds{get;}
 //打开/关闭操作
 public new DrawingContext RenderOpen();
 public new DrawingContext RenderAppend();
}
还提供PaintingVisual:
public class System.Windows.Media.Visuals.PaintingVisual:Visual
{
 protected SurfaceVisual();
 protected SurfaceVisual(UiContext Context);
 //表面属性
 protected Rect PaintingBounds{get;set;}
 protected Color FillColor{get;set;}//默认为透明—如果不透明更有效
 //打开/关闭语义
 protected StaticDrawingContext PaintingOpen();
 protected StaticDrawingContext PaintingAppend();
 //RenderCore语义
 protected abstract void RenderCore(Rect invalidRect);
 protected void InvalidateRender();
 protected InvalidateRender(Rect invalidationRect);
}
尽管RetainedVisual添加保留的指令流,但PaintingVisual实质上由表面支持。系统可虚拟化该表面并且仍保持呈现指令,只要符合性能要求。因此,该表面不能由用户访问。
PaintingVisual相对于RetainedVisual的一个差别是一个方法,它提供不允许动画的StaticDrawingContext。如果在任何地方使用动画的变元,则将抛出异常。另一个差别是“Append(追加)”将使指令流比存储器成本更便宜地增长。而且,PaintingBounds是要求和必需的,它实质上在用户上设置一个硬剪辑。注意,这与剪辑属性不同,因为它作为这个视件内容的边界,而Clip将剪辑这个视件及其所有子视件的内容。还实现RenderCore(类似于IRetainedVisual.Render),其中如果分辨率改变或者如果系统因某种原因需要重新呈现内容,则用户提供这种机制。
PaintingVisual有可能比SurfaceVisual更轻量,因为没有显式地由一个表面支持这个视件。而是,这是显示树中的一个节点,它处在由一个表面支持的某个较低点处。
为实现SurfaceVisual,用户应当创建RetainedVisual,调用DrawImage且随后改变场景后面的图像。在那种情况下,用户正显式地控制光栅化过程而不是让系统回调。存在立即模式API用于直接在图像上工作。这个API将允许用户取在那个图像上工作的StaticDrawingContext。注意,SurfaceVisual的API与hWnd、DUser Gadget或Trident显示树节点相似。“追加”内容(实际上-产生在已经在那里的内容上合成的小增量)是便宜的操作。实际上,追加内容没有存储器损失,不象用RetainedVisual,其中RenderAppend将使指令流变得更长和更大,有可能导致指数增长。由于支持这个视件的表面可出现和离开,因此要求视件实现“请求式(on-demand)”RenderCore虚拟。
PaintingVisual的一个主要使用场合是用于移植很大程度上围绕WM_PAINT绘画模型结构化的应用代码。这对于很少改变和密集的静态内容也是有用的。注意,PaintingVisual可由元文件或由真实的表面来支持。系统可以在运行时间决定哪一个更合适,例如,基于存储器和性能要求。然而,要保证的是,过了某个点,追加新内容将不再耗费更多的存储器。注意,系统在必要时可以在元文件和表面存储器之间切换。
顶层MIL对象
如可容易地理解的,提供各种对象用于在典型的窗口化情景中操作。注意,这些不必是形式类(例如,没有显式的调度器接口或对象)。
一个这样的对象包括视件树,它是包含要绘制的主要内容的对象。控件将直接从树的视件派生。视件是设备和上下文无关的。
呈现目标是要绘制视件的设备。这个对象(例如屏幕)可具有它自己的灰暗或无效机制,这是由传统的hWnd支持视觉系统所必需的。各种呈现目标包括窗口中的屏幕、Printer、Metafile、Surface和“Sub-window(子窗口)”,它是与场景的其它部分分开绘制的场景部分。这是支持交叉线程绘制的机制,并且等价于低层引擎的可合成对象。
其它绘制有关的对象包括VisualRender,它包括一个被配置为将视件树绘制到呈现目标上的对象,以及显示调度器对象,它知道何时将视件树绘制到呈现对象上。时间管理器是一个上下文对象,用于一组定时节点,并且是调度器启动运行的对象。
下面是绘制到屏幕的控制流程的一个例子:
1.用户以某种方式获得UiContext,并且开始修改视件树。这可以是在应用起动期间或者可能响应于UI输入事件。
2.灰暗通知向上传播Visual树。根视件知道它与哪一个视件呈现器相关联并且转发灰暗通知。这个通知是private(私有)的。
3.视件呈现器通过public事件报告它已经被改变并且与其呈现目标失去同步。
4.调度器决定何时以及何处实际校正这种情况并且使绘制发生。典型地,这是通过将一个工作项发送给分配器来完成的。然而,用户可以做其它事情。
5.用户让出UiContext并且允许Dispatcher运行。
6.Dispatcher运行并且调用调度器推迟的工作项。(很有可能聚结单一上下文中的任何推迟的工作项。而且,这可与布局系统步伐一致地运行以减少系统失效。)
7.调度器运行其主更新循环:
a.使TimeManager运行
b.运行布局,除其它以外
c.告诉视件呈现器呈现新的变化到呈现目标。呈现器然后:
i.遍历视件树的灰暗部分,并且更新内部高速缓存的边界框。
ii.调用所有必需的“请求式”视件来呈现。(默认地,“请求式”视件具有一个空的rect作为它们的边界,且因此不会调用它们,直到布局运行并设置它们为止。)
iii.再次遍历灰暗部分,并且发送必要的呈现更新到较低层的图形系统。
注意,视件系统一点也不知道分配器。只有调度器对象才关心那些细节。调度器可以进行任何适当的控制流程。
而且,存在增量视件呈现器和快照视件呈现器的概念。想要的是一个视件一次属于一个且仅属于一个增量视件呈现器。这个限制对于有效地在视件本身上高速缓存数据是必要的。然而,还具有一种方法来“快照”整个视件树到呈现目标是合理的。在这种情况下,在视件树与呈现器之间没有持久的连接。这可用于取得高分辨率屏幕抓取(grab)或用于将视件树(象它在屏幕上一样)直接发送到打印机。
Window扮演上面呈现目标的角色。它也是hWnd的受管理的替代。
class System.Windows.Media.WindowContext
 :IDisposable
{
 public WindowContext();
 //IDispose
 public void Dispose();
 public bool IsDisposed{get;set;}
 //窗口尺寸
 public Size Size{get;}
 public event EventHandler SizeChanged{add;remove;}
 //窗口有效
 public bool Islnvalid{get;}
 public event EventHandler IsInvalidChanged{add;remove;}
 //分辨率信息
 public ResolutionInformation ResolutionInformation{get;}
 public event EventHandler ResolutionInformationChanged{add;remove;}
}
窗口管理器控件在这个对象之外,然而它可以通过使属性(例如诸如Size)为读/写值来与WindowContext集成在一起,并且提供附加的属性诸如位置、窗口标题等。注意,Size属性代表物理(1/96英寸)单位的Window尺寸。这不是像素尺寸。注意,可能有这样的情况,因某种原因失去要呈现到窗口的数据,如视频模式切换或从本地控制台到远程终端服务器会话的切换。
VisualRender和VisualManager是其它对象,并且负责呈现Visual树到呈现目标。VisualRender提供简单的“一次拍摄(one shot)”模型,它在VisualManager建立视件树与这些视件要被呈现到的目标之间的保留连接的同时呈现到媒体。它支持“增量(incremental)”呈现到媒体。
下面是基VisualRender在一个实现中的示例:
public class System.Windows.Media.Visual.VisualRender:
 System.Threading.ContextAffinityObject,
 IDisposable
{
 //构造函数
 internal VisualRender();
 internal VisualRenderer(System.Threading.UiContext context);
 //ContextAffinityObject
 public UiContext Context{get;}
 public bool CheckContext();
 public void VerifyContext();
 public void SetContext(System.Threading.UiContext context);
 //IDispobale+
 public void Dispose();
 public bool IsDisposed{get;}
 //属性
 public Color BackgroundColor{get;set;}
 public Visual RootVisual{get;set;}
 //设备信息
 public Size RootSize{get;}
 public ResolutionInformation ResolutionInformation{get;set;}
 //呈现控制
 public void RenderNow();
}
该类不能公有地实例化,因为没有“默认”媒体。VisualRender也是一个ContextAffinity对象。
提供BackgroundColor属性:public Color BackgroundColor{get;set;}
这是视件管理器的默认背景色,它可默认这个对于VisualManager为透明的。然而,某些介质(诸如呈现给传统的hWnd)不能支持每像素透明性,因而每个VisualManager可以为这个属性定义自己的默认值。大多数应用将忽略这个属性,并且例如可设置为系统窗口背景色或透明。
RootVisual属性标识用于呈现的根视件:
public Visual RootVisual{get;set;}
这默认为null。当RootVisual属性是null时,VisualManager将背景色绘制到媒体上。
RootSize属性用虚拟单位返回呈现目标的尺寸。例如,对于由一个窗口支持的VisualManager,这将是该窗口的客户区尺寸:
public abstract Size RootSize{get;}
还提供分辨率信息:
public ResolutionInformation ResolutionInformation{get;set;}
每一媒体要求具有设备分辨率,即使它不是由像素支持的。例如,当打印时,即使捕捉到元文件,还是有必要通过VisualManager使分辨率信息可用,使得内容可以被优化用于该分辨率。注意,在元文件捕捉的情况下,可使用相对高的默认分辨率,同时允许用户直接配置分辨率。
为RootVisual设置的初始“世界到设备(world to device)”变换使得它在该视件中的一个单位等于设备上的1/96英寸。例如,如果有由一个192dpi的设备支持的ScreenVisualManager,则必须设置初始变换,因此在RootVisual的坐标帧中一个单位必须等于设备上的两个单位。在这种情况下,ResolutionInformation.PixelSize将返回(0.5,0.5)以表示每个像素在边上是1/48英寸。
VisualManager建立到根视件和呈现目标的长期连接并且跟踪差别:
public sealed class System.Windows.Media.Visuals.VisualRender:
 System.Windows.Media.Visuals.VisualRender
{
 //构造函数
 internal VisualManager();
 internal VisualManager(System.Threading.UiContext.context)
 //视件树灰暗public bool IsVisualTreeDirty{get;}
 public event EventHandler VisualTreeDirtyChanged{add;remove;}
}
WindowVisualManager(窗口视件管理器)是在屏幕上绘制的主要方法。它管理将Visual Tree(视件树)呈现到WindowContext:
public sealead System.Windows.Media.Visuals.ScreenVisualManager:
VisualManager
{
 //构造函数
 public ScreenVisualManager(WindowContext windowContext);
 public ScreenVisualManager(WindowContext windowContext,
 System.Threading.UiContext.context);
 //WindowContext
 public WindowContext WindowContext{get;set;}
}
绘制上下文
绘制上下文API提供本领域熟练技术人员所熟悉的“基于上下文的(context-based)”的编程模型,用于构造填充Visual或者被呈现到ImageData的视件内容的方法。本章节描述绘制上下文类,以及获得绘制上下文和枚举RetainedVisual/DrawingVisual中的视件内容所必须的类和入口点。
应用不直接构造绘制上下文,并且所揭示的绘制上下文版本是抽象类。有许多方法获得要将视件内容放入其中的绘制上下文。这些包括RetainedVisual.RenderOpen()或RetainedVisual.RenderAppend(),它们各自返回要向其发出指令的DrawingContext。其它方法包括IRetainedRender.Render()\DrawingVisual.RenderOpen()、DrawingVisual.RenderAppend()和PaintingOpen()或PaintingVisual.PaintingAppend()(尽管PaintingVisual不处理动画)。ImageData(或者ImageData的子类)有一种机制返回一个绘制上下文,用于呈现到固定分辨率位图表面上。ImageData也不处理动画。
下面阐述DrawingContext API:
public abstract class System.Windows.Media.StaticDrawingContext:
 ContextAffinityObject,IDisposable
{
 //没有public构造函数
 //向量图形绘制方法
 public abstract void DrawLine(Pen pen,Point point0,Pointpoint1);
 public abstract void DrawLine(Pen pen,
  Point point0,PointAnimationCollection point0Animations,
  Point point1,PointAnimationCollection point1Animations);
public abstract void DrawingRectangle(Brush brush,Pen pen,Rect
 rectangle);
  public abstract void DrawingRectangle(Brush brush,Pen pen,
   Rect rectangle,RectAnimationCollection rectangleAnimations);
  public abstract void DrawRoundedRectangle(Brush brush,Pen pen,Rect rectangle,double radiusX,double radiusY);
public abstract void DrawRoundedRectangle(Brush brush,Pen pen,
 Rect rectangle,RectAnimationCollection rectangleanimations,
 double radiusX,double radiusY);
public abstract void DrawEllipse(Brush brush,Pen pen,
 Point center,double radiusX,double radiusY);
public abstract void DrawEllipse(Brush brush,Pen pen,
 Point center,PointAnimationCollection centerAnimations,
 double radiusX,DoubleAnimationCollection radiusXAnimations,
 double radiusY,DoubleAnimationCollection radiusYAnimations);
public abstract void DrawGeometry(Brush brush,Pen pen,Geometry
 geometry);
 public abstract void DrawDrawing(Drawing,Point location);
 public abstract void DrawDrawing(Drawing drawing,
  Point location,
  PointAnimationCollection locationAnimation);
 //图像和视频绘制
 public abstract void DrawImage(ImageData image,Rect rectangle);
 public abstract void DrawImage(ImageData image,
  Rect rectangle,RectAnimationCollection rectangleAnimations);
    public abstract void DrawVideo(MediaData video,Rect rectangle);
 public abstract void DrawVideo(MediaData video,
  Rect rectangle,RectAnimationCollection rectangleAnimations);
 //文本绘制
 public abstract void DrawText(FormattedText text,Point origin);
 public abstract void DrawText(FormattedText text,
  Point origin,PointAnimationCollection originAnimations);
 public abstract void DrawGlyphs(GlyphRun glyphRun);
 //上下文状态方法
 public abstract void PushClip(Geometry clipGeometry);
 public abstract void PushOpacity(double opacity);
 public abstract void PushOpacity(double opacity,
  DoubleAnimationCollection doubleAnimations);
 public abstract void PushTransform(Transform transform);
 public abstract void PushBlendMode(BlendMode blendMode);
 public abstract void Pop();//应用于最后一个Pushed状态。
 //质量度量
 //枚举提示
 public abstract bool PreserveReadbackOrder{get;set;}//默认=false
 //Close()可以在所有Push还未Pop的情况下调用
 public abstract void Close();//与IDisposable.Dispose()一样
}
DrawingContext对象的大多数方法对于本领域熟练技术人员是自解释性的,然而应当注意,DrawingContext(绘制上下文)是ContextAffinityObject并且只从单一UiContext使用。DrawingContext对象也是IDisposable,并且是C#中所推荐的模式,例如,如果从RenderOpen/RenderAppend接收,则要在“using(使用)”语句中使用它们。而且,注意,诸如DrawArc、DrawPie、DrawBezier和DrawPolyline之类的方法不在这里。这些要求构造有关的Geometry,并且使用DrawGeometry(如下所述)。
而且,尽管有多个Push*方法,但只有单个Pop方法。这隐含着不能有重叠的属性。由Push*()建立的属性适当地组合。例如,Clip通过Intersection运算符组合,不透明性通过Multiplication操作组合,而变换通过ComposeTransform操作组合。
由于用户可以例如用一个null Brush或者用一个null Pen来调用DrawGeometry,因此用Brush和Pen两者的null来调用它是有效的,然而不会有任何内容被呈现或者被击中测试。
在非动画目标中使用时(例如,当直接呈现到光栅时)提供给绘制上下文的任何动画属性将抓住时刻零(尽管非动画目标或者可抓住时刻“现在”)。这允许为动态DrawingContext编写的代码更容易地过渡为使用不处理动画的DrawingContext。
在“保留的(retained)”visual中的内容的枚举与DrawingContext(通过它插入该内容)密切相关。如果需要,Visual的内容的枚举,和/或指令流的修改可通过Changeable机制来执行,如下所述。一般的思想是提供“进栈-模型(push-model)”枚举机制。
DrawingContext类本身提供一个接口以注册遍历内容的进栈-模式(push-mode),称为DrawingContextWalker的DrawingContext的子类,(具有大多数保持抽象的方法)。用户生成子类DrawingContextWalker,然后将一个实例传递给一个Visual以开始枚举。Visual回调适当的DrawingContext方法以发送它具有的内容。DrawingContextWalker还提供可在其上操作的一片状态以控制枚举如何进行(即,是否应当立即停止,例如)。
下面是DrawingContextWalker对象的示例代码:
  public class MyContextWalker:DrawingContextWalker
  {
    public void DrawLine(Pen pen,Point point0,Point point1)
    {
      Console.WriteLine(“Line from{0}to{1}with Pen{2}”,point0,point1,pen);
    }
    public void DrawRectangle(Bmsh brush,Pen pen,
          Rect rectangle,RectAnimationCollection rectangleAnimations)
    {
      Console.WriteLine(“AnimateRectangle with...”,...);
    }
  //等等,等等...
  }
//取任何RetainedVisual的内容(包括Control(控件)、DrawingVisual等)
MyContextWalker ctxWalker=new MyContextWalker();
ctxWalker.WalkContent(myFancyControl,0);//导致在ctxWalker上的调用
在DrawingContextWalker基类中提供WalkContent方法:
public abstract class DrawingContextWalker:DrawingContext
{
 protected DrawingContextWalker();//这让公有子类开始发生
  public void WalkContent(RetainedVisual visual,
   DrawingContextWalkOptions options);
  protected void StopWalking();
  //来自DrawingContext的抽象方法的实现
  //这在上下文遍历器上没有意义,并且如果被访问则将抛出异常
  public bool PreserveReadbackOrder{get;set;}
  //DrawText()扩展到GlyphRun中,所以它从不被回调,
  //因此我们不希望用户必须实现它。
  public void DrawText(...规则的...);//应当断言是否曾经被调用
  public void DrawText(...动画的...);//应当断言是否曾经被调用
  //其它方法保持抽象,并且子类器实现。
}
用户生成这个子类并且按需要实现所有抽象方法。用户随后创建对象的实例并且在其上调用WalkContent。WalkContent随后在它遍历Visual时回调适当的方法。任何这些方法的实现可以停止遍历,如果需要,通过调用protected方法StopWalking()。注意,当在Visual上的DrawingContext被打开用于呈现时开始遍历是非法的。
这些选项确定遍历如何进行:
  [Flags]
  public enum DrawingContextWalkOptions
  {
    IncludeAnimations=0×1
  }
如果IncludeAnimation置位,则遍历器用动画内容调用适当的方法。否则,将内容的瞬时值提供给DrawingContextWalker方法。
DrawingContext具有一个PreserveReadbackOrder布尔值,以通过DrawingContextWalker类返回的顺序和结构提供内容的顺序或结构给Visual。这默认为假,但当保存顺序是重要的时候,可在插入内容之前设置为真。例如,如上所述,可为DrawGeometry提供null Brush和null Pen。如果PreserveReadbackOrder为真,该指令需要被保存在Visual的状态中。如果PreserveReadbackOrder为假,则该实现随意丢弃这个指令。
注意,这个进栈方法比其它类型的安全方法具有许多优点,包括不需要并行类型集合来反射枚举的输出,并且没有必要要求在回调接口中进行堆分配。而且,可以在不创建对象以传回的情况下直接调用这些方法,DrawingContext接口已经存在,并且在Visual本身上不需要附加API以考虑遍历。
修改视件内容是另一项考虑内容。向VisualContent表达修改的一种方法是使用资源(Pen,Brush等),在此所述的是Changeable子类,具有StatusOfNextUse=UseStatus.ChangeableReference。这允许由应用保存的对在受管理结构中的数据的引用被发送到DrawingContext中。这代表允许作出改变的统一方法,并且因为这些对象是在它们已经被显式地设置成的已知状态,所以实现知道哪些对象有可能被修改。注意,它不允许,例如,指令顺序的改变,或者添加或删除指令(尽管有RenderAppend()用于添加)。
绘制
Drawing类包含绘制命令集合。确切地它等价于存储在DrawingVisual上的内容,并且由DrawingContext建立。在不可改变时,Drawing没有上下文仿射性(context affinity),并且因而在它本身是不可改变时可以跨上下文和在默认属性页中使用它和有关的类DrawingBrush。
它不直接支持层次结构,因为它没有提供重复子对象或寻找父亲对象的方法,但通过DrawingContext,可以将Drawing绘制到另一个Drawing中。可以通过DrawDrawing(Drawing)将Drawing绘制到DrawingContext中,并且它可用作DrawingBrush的内容描述。
Drawing是完全可动画的(animatable),并且以与RetainedVisual相同的方式支持读回/重复。
public class System.Windows.Media.DrawingCollection:Changeable
{
 //构造函数
 public Drawing Collection();
 public new DrawingCollection Copy();
 //属性
 public Rect Bounds{get;}
 //打开/关闭操作
 public DrawingContext Open();
 public DrawingContext Append();
}
Changeable模式
为了说明,本发明将主要在编程环境的上下文中描述,在该环境中构造、使用和修改图形场景中的示例对象。然而,如将理解的,尽管本发明在图形相关的编程环境中提供显著的好处,但本发明不限于图形相关的编程环境,而是更一般地应用于许多其它类型的编程环境。
在一个实现中,本发明提供从公共基类例如System.Windows.Changeable派生的单组类型。任何类可以是可变的,通过从Changeable类派生并因而获得Changeable提供的类型语义。例如,在图形编程中,对象模型包括Brush、Pen、Geometry、FloatAnimation、GradientStop、Segment等等,如在前述美国专利申请序列号10/402,268中主要描述的。例如,绘制画刷的层次结构可以象下面这样:
Object:Changeable:Animatable:Brush:TileBrush:DrawingBrush。
为了基本用法,changeable对象包括下列属性和方法:
public class System.Windows.Changeable
{
 public bool IsChangeable{get;}//默认为true
 public Changeable Copy();
 public void MakeUnchangeable();
}
IsChangeable属性描述changeable对象是否可以被修改,取决于它的当前值。例如,试图设置画刷的不透明性属性将只有在画刷对象具有等于true的IsChangeable属性时才成功。否则,将引发异常。当被构造时,changeable对象默认地具有等于true的IsChangeable属性,并且因而是立即可修改的。
如图14所示,接收请求1402,诸如通过源于应用程序的函数调用,它被指向changeable类1404。通常,包括状态机1408的请求处理程序1406,处理这些请求并通过支持数据结构1410保存状态和对象数据,基于当前的属性状态,以适当的属性状态在克隆的拷贝1412中克隆数据结构,如下所述。可抛出异常1414,诸如当请求寻找一个从当前属性状态内不允许的转变时。下面参考图15-17描述属性状态。
应当注意,针对changeable类的函数调用可直接或间接地处理。例如,图14中请求处理程序1406可包括一个API集合,提供到状态机的接口。可替换地,请求处理程序1406可包括中间件代码,将在一个操作系统中接收的请求转换成由另一个操作系统处理的API调用。因而,如在此使用的,请求通过请求处理程序“使”所请求的行为发生,不管实际的状态机处理在何处发生或者在何处提供数据结构和类。
如此,(除其它机制以外),应用可通过“新”请求构造changeable对象,将值设置它们之中,使用它们,继续将值设置到它们之中,并且继续使用它们。
下面是应用如何创建纯色的画刷(scb)的例子,修改画刷具有纯色(红)并使用画刷使按钮的背景为红色:
SolidColorBrush scb=new SolidColorBrush();
scb.Color=Colors.Red;
Buttonl.Background=scb;//这限制为“使用(use)”(如下所述)
“使用(using)”一个值的概念具有特定的含义,即,值只被认为在某些条件下使用。这些条件包括当将值设置到属性系统属性中时,当使用值作为更复杂的changeable中的子-对象时,以及当在DrawingContext命令中使用值时等等。注意,系统扩展者可以容易地定义使用被限制为“使用(use)”的changeable对象的其它实例并修改对象的可改变状态。
当在这些受限制种类的使用之一中使用值时,从用户-模型观点,作出它的克隆,并且该克隆具有设置为false的IsChangeable属性。注意,实际上,没必要创建克隆,并且当创建一个克隆时,它没必要是深的(在对象层次结构中,如下所述)。虽然,从模型的观点,作出克隆是适当的考虑,并且因而如在此使用的,“克隆(clone)”的概念覆盖了实际创建的克隆、部分创建的克隆和/或从模型的观点即使没必要创建而逻辑地创建的克隆。克隆是实际获得使用的内容,并且默认地,不能修改克隆。
如上所示,changeable对象还包含方法,包括Copy()和MakeUnchangeable()。对Copy()方法的显式调用创建可改变的拷贝,且拷贝的IsChangeable属性设置为true。这个调用不改变调用该方法的对象。MakeUnchangble()方法可在任何changeable上被调用,并且修改IsChangeable属性使它为false,(除非已经为false,在这种情况下调用没有效果)。
上面的机制促进代替一个属性的模式。为改变一个changeable对象,IsChangeable属性值必须为true。由于对象的受限制使用创建了不可改变的克隆,因此该对象必须通过Copy()方法拷贝、修改和再次使用。这实际上用一个新对象(是原始的修改的拷贝)代替初始对象。下面阐述它的例子。注意在使用中的changeable是已经使用的那个,并因而通过上面的定义,是不可改变的,因为在使用时IsChangeable属性设置为false。因而,changeable不被修改,而是拷贝和代替一个changeable。注意,关于changeable,只有单一类型组,从编程观点它通常是非常想要的。而且,真正的可变性是通过附加属性提供的,如下所述。
如上所述,直接创建画刷,修改它并使用它。下面阐述绘制操作中简单使用的例子:
SolidColorBrush scb=new SolidColorBrush();
scb.Color=Colors.Red;
ctx.DrawRectangle(scb,...);//这是“使用”
scb.Color=Colors.Green;
ctx.DrawRectangle(scb,...);//这是“使用”
执行上面的指令绘制一个红色矩形和一个绿色矩形。注意,‘scb’实际上在每次使用它时被克隆。
一个使用线性渐变画刷(lgb)的更复杂的结构,其中颜色从一个停止符到另一个改变(例如,线性地),在下面阐述:
LinearGradientBrush lgb=new LinearGradientBrush();
GradientStop gs1=new GradientStop(Colors.Red,0.3);
GradientStop gs2=new GradinetStop(Colors.Blue,0.2);
lgb.Stops.Add(gs1);//这是gs1的“使用”
lgb.Stops.Add(gs2);//这是gs2的“使用”
Button2.Background=1gb;//这是lgb的“使用”
这里,这个过程是在更复杂的值的定义中建立值(GradientStop)并使用它们。
考虑另一个例子,它针对改变一个按钮(Btn)的背景的不透明性(范围可以从零到一)为0.4。在这个特定的使用中,将Background拷贝到一个具有设置为true值的IsChangeable的对象中,修改背景,并且设置回来。
Brush b=Btn.Background.Copy();//取IsChangeable拷贝
b.Opacity=0.4;
Btn.Background=b;//“使用”修改的值
也要注意,在最后一行中对“Btn.Background”的赋值切断任何可能出现的任何继承或属性页值。
在对象层次结构中较深的修改与较浅的修改相比,对于用户而言显得没有差别:
Brush b=Btn2.Background.Copy();
LinearGradientBrush lgb=(LinearGradientBrush)b;
lgb.Stops[1].Color=Colors.Green;
lgb.Stops[0].Location=0.2;
Btn2.Background=b;
注意,Copy()只需要在顶层对象上调用,并且不是单独的GradientStop。这是因为系统照管确保具有为true的IsChangeable属性的对象的子对象在它们被访问时自己用等于true的IsChangeable设置。
图15示出一个状态图,表示在基本用法中changeable对象的状态,当新创建时以IsChangeable属性等于true开始。一般而言,实箭头示出对象的状态从当前状态转换到目标状态,而任何虚线箭头表示让对象保持为相同但在目标状态中创建新对象的操作。在这个状态图中,有两个状态,并且在Copy()或MakeUnchangeable()任一个被调用时且当以限制为使用的方式使用对象时发生转换,如上所述。注意,从任一状态调用Copy()方法导致一个新值且其IsChangeable属性设置为true,同时调用MakeUnchangeable()导致目标值是设置为false的IsChangeable。
上面的描述提供一个直接的、自洽的模型,描述了只有两个状态的基本用法,Copy()和MakeUnchangeable(),以及“使用”Changeable值的概念。然而,关于改变,上面修改示例基于代替的概念,即拷贝现有项,在原地改变它,并且将它拷贝回去。这隐含着堆分配(这有可能是重要的,取决于要作出的改变有多深,和对象本身用于浅克隆有多宽),并且在编程者身上附加了保持某种机制以找出要修改属性的路径的负担。
依照本发明的一个方面,为增加对真正的值可变性概念的支持,将另一个属性添加给这个模型,名为StatusOfNextUse,类型是UseStatus。注意,防止单一属性模型中可变性的基本问题是值的受限制使用无条件地导致具有等于false的IsChangeable属性的结果值。StatusOfNextUse属性解决这个问题。
public enum System.Windows.UseStatus
{
 Unchangeable,
 ChangeableCopy
}
默认地,StatusOfNextUse属性是UseStatus.Unchangeable,但可设置为UseStatus.ChangeableCopy,由此使用这样设置的值将导致使克隆对象具有设置为true的IsChangeable属性。结果,对象值可以在原地修改,而没有任何附加的堆分配。
而且,因为使用中的值在这个模型中可以变化,当这样的改变发生时,通过一个简单的改变事件提供通知。而且,由于对象不再是不可变的,通过UiContext成员提供上下文-仿射性。注意,当对象是可变的时候,这具有null值。否则它属性在其中创建它的UiContext。得到的Changeable类定义变成:
public class System.Windows.Changeable
{
 //从上面的“基本用法”沿袭
 public bool IsChangeable{get;}//默认为true
 public Changeable Copy();
 public void MakeUnchangeable();
 //新成员
 public bool CanMakeUnchangeable{get;}//MakeUnchangeable(使不可改变)会成功吗?
 public UseStatus StatusOfNextUse{get;set;}//默认为Unchangeable
 public event EventHandler Changed{add;remove;}
 public UIContext UIContext{get;}//当不可变时null
}
上面简单的浅可变性的例子描述了改变Brush上的不透明性的要求,其中代码必须在每次不透明性被改变时运行。相反,关于基于StatusOfNextUse属性的可变性机制,首先Btn.Background本身具有值为true的IsChangeable属性:
Brush b=Btn.Background.Copy();//取IsChangeable拷贝
b.StatusOfNextUse=UseStatus.ChangeableCopy;
Btn.Background=b;
上面使用了(在受限制的使用中)一个StatusOfNextUse为UseStatus.ChangeableCopy的值,因此结果本身是可改变的。一旦设置,编程者在需要时可以作出修改,如下例:
Btn.Background.Opacity=0.3;
编程者只要需要,可以随时作出这样的修改,并且在后续设置上没有任何对象分配的情况下,修改将直接发生。
注意,上面的例子没有描述Btn.Background如何进入第一位置中,并且因而需要通过Copy()产生它的拷贝。在故意的可变性情况中,编程者想要创建要修改的背景,这么做的较佳方法可以是直接的,如下例:
SolidColorBrush b=new SolidColorBrush();
b.Color=Colors.Red;
b.StatusOfNextUse=UseStatus.ChangeableCopy;//直接设置这个
Btn.Background=b;
这里,编程者只要需要就可以指定不透明性(Btn.Background.Opacity=...),因为画刷最初创建时,StatusOfNextUse等于UseStatus.ChangeableCopy。
应当注意,使用基于代替的模型而不是基于变化的模型,要给出上面的例子并不特别困难。这是因为改变是在第一层作出的,并且始终是代替而不是变化并不显得代价特别大。事实上,当只需要有限的可变性时,这是有效的技术。然而,当对在对象中较深的值作出改变时,变化模型显然占优势。
如这样较深可变性的一个例子,考虑LinearGradientBrush(1gb),其中编程者反复地想要改变第七个停止符(lgb.Stops[6])的颜色。编程者可以使用与上面相同的代码来将一个可变版本安装到Btn.Background中:
Brush b=Btn.Background.Copy();//取IsChangeable拷贝
b.StatusOfNextUse=UseStatus.ChangeableCopy;
Btn.Background=b;
之后,编程者可以反复地作出想要的改变:
LinearGradientBrush lgb=((LinearGradientBrush)Btn.Backgroun);
lgb.Stops[6].Color=...某种新颜色...;
编程者也可以访问“lgb”变量一次,另外存储它,并然后反复地设置到它中,这是非常有效的。
图16是图15状态图的扩展,具有由添加的StatusOfNextUse属性代表的附加状态。注意,模型只是稍微地更复杂,因为图15的基本状态图具有两个状态和七个转换,而可变性状态图具有三个状态和十一个转换。如可以从图15看到的,明显增加的是(StatusOfNextUse==ChangeableCopy)状态,和在该状态外的“使用”转换,它导致IsChangeable属性值设置为true的新拷贝。
如在图15中,调用Copy()方法导致具有IsChangeable属性等于true的新值,且StatusOfNextUse属性设置为Unchangeable。同样,MakeUnchangeable()方法调用导致IsChangeable属性设置为false的目标值。注意,即使已经通过可变性增加了灵活性,但这些常量也不改变。
存在某些不允许在StatusOfNextUse等于ChangeableCopy时使用的情况,因为后续的修改不是真正良好定义的,或者被显式地禁止。它的例子包括试图修改在共享的默认样式表中的值,或者设置非局部属性引擎属性。在这样的情况下,禁止这种使用的子系统将或者选择提出一个异常,或者使值本身不可改变。推荐提出一个异常,向编程者更清楚地表示发生了什么从而避免以后的混淆。
而且,存在不能使changeable对象不可改变的情况。例子包括VisualBrush,(如在前述美国专利申请序列号10/402,268中描述的),其中在下面的视件不能被限制改变,并因此VisualBrush是“不可改变”的状态是没有意义的。动画和VideoData(因为它们是时变的)也是例子。试图在这类对象上调用MakeUnchangeable()将提出异常,或者更差,使对象留在一个坏状态中,因为可能已经使的它的部分成为不可改变而其它部分不是。这些问题可以通过另一个属性CanMakeUnchangeable来避免。如果这个属性返回“true”值,则保证MakeUnchangeable()成功,在这些调用之间不提供对对象的改变。
偶尔在StatusOfNextUse与CanMakeUnchangeable之间会发生语义上的冲突。如果CanMakeUnchangeable等于false,则用于StatusOfNextUse的UseStatus.Unchangeable值事实上是无意义的,因为下次使用不可能是不可改变的。因此,当在CanMakeUnchangeable等于false时查询StatusOfNextUse时,它从不返回UseStatus.Unchangeable。相反,当它其它情况下已经返回了UseStatus.Unchangeable时,它返回UseStatus.ChangeableCopy。
上面提出了一种模型,其中每次(受限制的)使用changeable(IsChangeable等于true)对象导致产生该对象的拷贝,并且取决于StatusOfNextUse的值,可以或者不可以不改变地“使用”它本身。上面的模型不提供的是在多处使用一个值,和保存到该值的共享引用。例如,在上面的模型中,编程者不可以创建LinearGradientBrush,在两个Button控件上使用它,以及随后改变LinearGradientBrush一次以影响两个控件。而是编程者必须使用它两次,从控件中取回画刷,随后独立地设置每一个。通常,这个模型产生编程者最期望的和/或至少是令人惊讶的结果,但存在需要附加功能的情况。
一个这样的情况是Animation,其中,如果编程者想要创建一个具有n个元素的场景,每个元素相应于同一时间线,该时间线必须被克隆n次,并n次询问BeginIn()。一种更好的方法,从性能和效率两者的观点,也为了编程模型便利,是共享到单一时间线的引用,在其上调用BeginIn(),并且在适当的时候让它传播。
为支持这种情况,为UseStatus枚举提供第三个值,ChangeableReference。UseStatus现在看上去如下:
     public enum System.Windows.UseStatus
     {
       Unchangeable,
       ChangeableCopy,
       ChangeableReference
    }
当使用(以受限制的方式)具有StatusOfNextUse设置为UseStatus.ChangeableReference的changeable对象时,该值不再被拷贝。相反,分出一个对现有值的引用,并且对该值(或者之前或之后分出的引用)的后续修改将影响使用的结果。换言之,现在有可能以任意数量的使用来共享changeable值。
下面是元素层用法的例子:
Brush b=new SolidColorBrush(...);
b.Color=Colors.Yellow;
b.StatusOfNextUse=UseStatus.ChangeableReference;
Btn1.Background=b;
Btn2.Background=Btn1.Background;
Btn3.Background=Btn2.Background;
Btn4.Background=b;
//这里,所有四个按钮是黄色的
((SolidColorBrush)Btn3.Background).Color=Colors.Purple;
 //它们改变为紫色,并且通知它们。
在上面的例子中,描述了一个简单的绘制操作,它产生两个矩形,一个红,一个蓝:
SolidColorBrush scb=new SolidColorBrush();
scb.Color=Colors.Red;
ctx.DrawRectangle(scb,...);//这是“使用”
scb.Color=Colors.Green;
ctx.DrawRectangle(scb,...);//这是“使用”
这是所希望的行为。然而,如果编程者代替想要共享画刷,而仍是可改变的,则可使用下面的代码:
SolidColorBrush scb=new SolidColorBrush();
scb.UseResult=UseResult.ChangeableReference;
scb.Color=Colors.Red;
ctx.DrawRectangle(scb,...);//这是“使用”
scb.Color=Colors.Green;//初始的矩形变成绿色
ctx.DrawRectangle(scb,...);//这是“使用”
这里,两个矩形都是绿色的。如果以后改变颜色,例如scb.Color=Colors.Yellow,则两个矩形都变成黄色。注意,ctx.DrawRectangle(...)好象是立即模式绘制命令,然而,它实际上建立要保留并随后显示的显示列表/元文件。
从用户-模型的观点,ChangeableReference模式保证使用changeable对象的各方将被通知对该值的任何改变。这将通过“Changed”事件来完成,它象其它事件一样,是一个组播委托。为了实现,系统需要确信单一通知汇点(sink)的多重使用不通知每个使用的汇点。而且,清除机制在移除项时有要求,以便在连接到汇点的使用离去时只移除该汇点。完成这个的一种方法是引用计数委托。当前的实现可通过一个私有的数据结构如RefCountedMulticastEventHandler来实现这些要求。
图17是基于图15和16的状态图,但具有增加的一个ChangeableReference状态(通过在StatusOfNextUse属性中的另一个设置)。注意,依照本发明,ChangeableReference状态和该节点的Use(使用)转换不产生拷贝。相反,受限制的使用导致下次使用属性的状态保持在可改变的引用状态,从而提供真正的可变性。而且,注意,尽管图17比图15和16的更复杂,但Copy()和MakeUnchangeable()方法保持不变;Copy()方法仍导致具有IsChangeable属性为true和StatusOfNextUse属性为Unchangeable的新值对象,以及MakeUnchangeable()方法仍导致具有IsChangeable属性为false的目标值。
应当注意,连同单一类型组的优点,本发明为编程者提供显著的灵活性。例如,由应用构造的大多数值一般不是可变的,因为不可变的值消耗较少的资源。然而,如上所述,可变性是可提供的,给编程者有力和直观的方法来以高性能改变值,尤其是深的值。也要注意,尽管图17中没有示出,但在其中创建新类型的状态(IsChangeable为true,StatusOfNextUse属性为Unchangeable)是一个可能的默认状态。因而,在可替换的实现中,类型可处在创建之后的另一状态中,例如,IsChangeable属性为true,StatusOfNextUse属性为ChangeableReference),诸如默认为可变的值。
转到本发明的操作的说明,在处理对象的深属性时,本发明提供明显的优点,称为暂记(dotting-down)。例如,考虑下面的:
GeometryColloection g;
g.Geometris[12].Figures[2].Segments[0].Points[17]=
new Point(0.2,0.3);
对几何图形对象‘g’的深访问是被称为暂记的一个例子。注意,对属性(Geometry,[12],Figure,[2],Segment,[0]和Point)的访问是调用属性取得者(getter),不是设置者(setter);[17]是导致正在调用的设置者的唯一的属性访问。编程语言通常不能区别是为了设置较深的属性值而访问属性,还是为了读取较深的值的访问。
当暂记从不可改变的对象开始时,访问局部成员变量。一个例子包括访问一个还没有通过使用“ChanegableValue”属性使其可改变的元素。
当属性取从可改变的对象开始,所得到的值同样是可改变的,因此可以变化它。为此,如果已经可改变,在父亲上的属性取得者直接返回子-对象(sub-object),或者产生子-对象的浅克隆,将它设置到局部成员中,并返回该克隆。注意,在首次运行和分配和赋给浅克隆之后,按照不要求堆分配,这些特性使上述代码释放。
本发明的一个方面是,只在必要时执行请求式浅克隆。这最大化了共享,最小化了堆分配,允许无堆分配的修改,并且不将克隆的概念强加到用户模型上。对于较深的树以及在三维上工作时,这变得更重要。为此,Copy()方法提供深拷贝的错觉,但实际上首先只产生浅拷贝,随后懒洋洋地在需要时产生较深的拷贝。这样的暂记提供显著的性能改进。
依照本发明的一个方面,在changeable上的另一个属性(通常对于应用是不可见的)是changeable具有一个已改变事件(类型为EventHandler)。当Changeable的属性改变时,在该changeable上的Changed委托获得调用,并且以正在改变的changeable作为发送者。通过暂记作出浅克隆的行动使已改变事件处理程序进栈到浅克隆中。这允许后续的改变在较深的元素上发生并设置适当的事件处理程序。注意,Changed事件也存在,以便除属性系统之外的客户机能使用这个系统和注册通知。
对已改变事件处理程序的修改向下传播至子-对象。另外,对涉及其它changeable的changeable本身的修改(例如,添加一个changeable子-对象到changeable对象,移除一个等等)导致递归地从旧的中移除包含的changeable的事件处理程序并将它进栈到新的中。
图18-23示出浅-克隆和暂记如何工作,基于下面这个例子的代码:
LinearGradientBrush lgb=new LinearGradientBrush();
lgb.Stops.Add(new GradientStop(Colors.Red,0.3));
lgb.Stops.Add(new GradientStop(Colors.Blue,0.2));
lgb.Stops.Add(new GradientStop(Colors.Green,0.1));
Btn1.Background=lgb;
Btn2.Background=lgb;
如图18所示,两个Button1和Button2指向同一线性渐变画刷1802,它具有停止符节点1804和在下面分层地排列的指定停止符的属性。考虑代码:
Btn1.Background=Btn1.Background.Copy();
执行这个代码导致由Button1产生并指向的线性渐变画刷1802的拷贝1902,如图19所示。
执行这个代码:
LinearGradientBrush lgb=((LinearGradientBrush)Btn1.Background);
lgb.Stops[1].Color=Colors.Orange;
提供对具有IsChangeable==true、以Changeable为值的Changeable对象的访问,意味着所检索到的内容保证是可写的。如在图20-22中主要表示的,执行这个代码导致(1)插入到层次结构中指向每一个独立的停止符的另一个停止符节点2004(图20);(2)要产生第二停止符节点(在图20和21中标签为2010的停止符节点[1],它在下面具有“蓝色”属性)的拷贝2110(图21),使得这个拷贝的父亲节点,先前拷贝的停止符节点2004,具有作为其子节点的拷贝2110(代替原来的用于蓝色属性的停止符节点2010);以及(3)将这个节点2110的蓝色属性改变成橙色,如图20所示。注意,在图中Orange(橙)是由菱形表示的值类型,并且后续的改变不导致分配,诸如在图23中改变为颜色Red(红)。
当在不可改变的状态中,changeable对象可从任何上下文中读出或写入。如果在可改变的状态中,则在构造时间确定的UiContext可用于关联于changeable对象,以便只允许从该上下文访问。如果以后调用MakeUnchangeable,则上下文变成null。而且,任何时候进行changeable的Copy(),新拷贝就从调用者取得UiContext,而不是从源changeable的上下文取得。API当不可变时在为null的changeable上提供一个UiContext只取属性。这个属性是公有的,因此应用可以告诉是否可访问一个给定的对象。
用null传递到构造函数构造的changeable对象将用一个null UiContext定义。如果changeable对象具有nullUiContext和IsChangeable属性设置为true,则应用需要管理任何可能引起的线程竞争问题。在这种情况下,系统不阻止来自多个上下文的同时访问。
一种情况可以发生,由此changeable对象正在试图将另一个changeable对象嵌入它之中(例如,在线性渐变画刷中设置一个渐变停止符),并且UiContext不匹配。例如,考虑具有UiContext为A的LinearGradientBrush1gb,而GradientStop gs具有UiContext为B和等于ChangeableReference的StatusOfNextUse两者。试图将gs设置到lgb中将导致一个异常被提出,因为这是混合UiContext的试图,它是被禁止的。
当对一个changeable对象作出改变时,提出Changed事件,并且提供该changeable作为事件处理程序的发送者对象。然而,存在发送不希望真正改变的对象时的情况,并且其中具有不同的对象作为发送者将更有帮助。它的一个例子是关于动画的对象,其中一个动画(本身为changeable)保持在描述其动画行为的时间线(有时称为时钟)上。诸如Pause()之类的事件在时间线上发生,并且不是动画而通常是应用想要知道动画已经暂停了。
各种解决方案都是可能的,诸如在changeable链上激发已改变事件。这提出了许多问题,包括决定在哪里停止、甚至在什么也没有接收时引起具有多得多的被激发事件的通知风暴和/或使用这些事件,并且按照设计,changeable不知道它们的父亲,而是通常只知道要在改变的事件中通知什么。拥有一个在其中changeable跟踪它们父亲的方案将要求额外的存储器和簿记。然而还是可以实现这样的解决方案。
另一个解决方案是实现一个changeable,使得发送者是可改变的对象,而不是真正改变的里面的changeable。实现PropagateEventHandler,以不使它收到的处理程序进栈,而是另外存储该处理程序,创建一个新的局部处理程序,当被调用时,调用所存储的处理程序,但用changeable作为发送者变元。新的局部处理程序被进栈到changeable子对象上的PropagateEventHandler。注意,这个技术截取每个事件处理程序,要求PropagateEventHandler在以‘false’调用时被正确地处理(当处理程序要被移除时),因而要求执行簿记。
注意,这个解决方案没有显式的BeginChange/EndChange辖区机制,使它面对异常时更直接和健壮(由于没有涉及的模态,并且没有可以获得跳过的EndChange()由非预料的异常传递)。然而,BeginChange/EndChange存在,以允许对象的“取得者(getter)”不必产生它们正在取得的值的浅克隆,当这些克隆被冻结并且系统不是在写模式中时。否则,这些冻结的值,在写模式中,取得从它们产生的浅克隆。结果,比BeginChange/EndChange更频繁地使树剧增,并且在绝对没有涉及设置而只有取时才可以这么做。然而,如果正在要以其开始的不可改变的值上调用取得者,它将不产生浅克隆(注意,这与正在可改变的值上调用取得者不同,并且正在通过“取(get)”获得的值是不可改变的,这是克隆操作发生的地方)。
作为例子,如果访问Btn.Background.Opacity,并且Btn.Background是不可改变的(例如,作为默认地),则不进行拷贝。代之以在“Btn.Background=Btn.Background.ChangeableValue”等发生时将发生拷贝,意味着只有在使用时才发生拷贝的开销。换言之,如果不是表达要改变值的意图,则任意“取(getting)”不引起拷贝成本。注意,如果值保持它们“最后创建的克隆”的概念,则该克隆可以在对象的使用上被分出,只要该对象自从产生克隆起没有被改变过(这样的改变只导致让该高速缓存的克隆离开)。这允许更多的共享。而且,注意,控件实现者通过参加这个模式,其不适当的负担与该模式对于用户的有用性是不相同的。同样,如果提供类型可扩展性,则写MediaTypes应当不过度复杂。
为控件实施者提供具有与处理任何其它值相同的处理Changeable的模型。例如,下面的代码提供具有类型为Brush的AlternateBrush属性的Grid控件:
public static readonly DynamicProperty AlternateBrushID=...;
private Brush_alternateBrush;
public Brush AlternateBrush
{
        get
        {
         return ComputeValue(AlternateBrushID,
                       ref_alternateBrush);
        }
        set
        {
      WriteLoeal(AlternateBrushID,value);
       }
  }
注意,这与参加属性系统的一般属性相同。那是因为writeLocal将为从Changeable类派生的深属性进行特殊处理。
changeable类型实施者需要在修改changeable(例如属性)的任何对象上的一个一行导言和一个一行附言。而且,在访问changeable的状态(例如属性取得者)的对象上需要一个简单的一行导言。所需要的是CloneCore()、MakeUnchangeableCore()、PropagateEventHandlerCore()、PropagateEventHandlers()(注意最后三个只是具有其它Changeable作为属性的类型所需要的),并且还需要的是Copy()的类型安全-包装者。
下面的例子来自引用的原型,包括GradientStop的(人造的)例子,GradientStop是一个简单的changeable类型(它是简化的,因为它没有一个子类型是可改变的)。注意,实际上,非常少的changeable将是这么简化的,因为包括动画集合(它本身是一个changeable)的任何对象将更复杂:
public class GradientStop:Changeable
{
 public GradientStop()
 {
 }
 public GradientStop(Color color,float location)
 {
 _color=color;
 _location=location;
}
public Color Color
{
 get
 {
  ReadPreamble();
  return_color;
}
set
{
//这是用于设置简单值类型的模式。
WritePreamble();
if(_color!=value)
{
   _color=value;
   WritePostscript();
  }
 }
}
public float Location
 {
  get
  {
   ReadPreamble()
   return_location;
  }
  set
  {
   //这是用于设置简单值类型的模式。
   WritePreamble();
   if(_location!=value)
   {
   _location=value;
   WritePostscript();
   }
  }
 }
 //创建新的类型安全版本的Copy()
 public new GradientStop Copy()
 {
  return(GradientStop)base.Copy();
 }
protected ovverride Changeable CloneCore(bool shallowClone)
{
 //这里,当所有成员是值类型时,将浅和深视为相同
 return new GradientStop(_color,_location);
}
 private Color_color;
 private float_location;
}
下面是LinearGradientBrush的例子,它是更复杂的changeable类型(因为其某些子类型,即GradientStop,本身是可改变的):
public class LinearGradientBrush:Brush
{
 public LinearGradientBrush()
 {
 }
public LinearGradientBrush(GradientStop stopl,Gradient stop2,
 double opacity)
 :base(opacity)
{
 //通过属性赋值导致″使用″参数。
 Stop1=stop1;
 Stop2=stop2;
}
 public GradientStop Stop1
 {
  get
  {
   _stop1=(GradientStop)EmbbedChangeableGetter(_stop1)
 return_stop1;
}
set
{
 if(_stop1!=value)
{
_stop1=(GradientStop)EmbeddedChangeableSetter(_stop1,value);
         WritePostscript();
        }
       }
      }
      public GradientStop Stop2
      {
       get
       {
        _stop2=(GradientStop)EmbbedChangeableGetter(_stop2)
        return_stop2;
       }
       set
       {
        if(_stop2!=value)
        {
_stop2=(GradientStop)EmbeddedChangeableSetter(_stop2,value);
         WritePostscript();
  }
 }
}
//原地修改为r/o(或者检查它是否完成)。
//帮助者检查变元是否为null。
protected override bool MakeUnchangeableCore(bool checking)
{
 return Changeable.MakeUnchangeable(_stop1,checking);
 &&Changeable.MakeUnchangeable(_stop2,checking);
}
//事件改变的传播
protected override void PropagateEventHandlerCore(EventHandlerhandler,
 bool adding)
{
Changeable.ModifyHandlerIfChangeable(_stop1,handler,adding);
Changeable.ModifyHandlerIfChangeable(_stop2,handler,adding);
}
protected override Changeable CloneCore(bool shallowClone)
{
  //始终使用成员字段而不使用属性用于克隆。
 //否则你无意中引起特别浅的拷贝。
 if(shallowClone)
 {
  return new LinearGradientBrush(_stop1,_stop2,_opacity);
 }
 else
 {
  return new LinearGradientBrush(
   (GradientStop)Changeable.CloneDownToUnchangeable(_stop1)
   (GradientStop)Changeable.CloneDownToUnchangeable(_stop2,
   _opacity);
 }
}
 private GradientStop_stop1;
 private GradientStop_stop2;
}
changeable对象模型被划分成一个公有部分和一个扩展者(extender)和作为宿主者(hoster)看见的部分。再次注意,尽管对于使用这些类型的组件编写者事情是很简单的。
//PUBLIC API。每个人期望使用这部分API。
//在这部分之外的一切将不让编辑者看见。
public abstractclass System.Windows.Changeable
{
 public bool IsChangeable{get;}//默认为true
 public Changeable Copy();
 public void MakeUnchangeable();
 public bool CanMake Unchangeable{get};
 public UseStatus StatusOfNextUse{get;set;}//默认为false
 public event EventHandler Changed{add;remove;}
 public UIContext UIContext{get;}//如果IsChangeable==false则null
 public bool AllowChangeableReferenceOverride{get;set;}//默认为false
 //下面示出protected的材料。
}
 Public enum System.Windows.UseStataus
{
 Unchangeable,
 ChangeableCopy,
 [EditorState.Advanced]
 ChangeableReference
}
public class System.Windows.Changeable
{
//组件编写者API。这是由组件编写者使用的。
//(注意:没有东西是组件编写者需要知道的。)
//扩展者API。这是由编写新Changeable的人使用的。
protected changeable();//使用UIContext.CurrentContext
protected Changeable(UIContext context);
//子类型实现这个以提供如上所述的克隆。
protected abstract Changeable CloneCore(bool shallowClone);
//子类实现冻结它们的复杂子类型(当
//‘checking’为false时),或者要检查它们是否可以(当
//‘checking’为true时)。注意,当checking为false时,返回的
//布尔值不产生实际意义,但实施者要在这种情况下返回‘true’,
//以便调用代码(象上面的例子)正确地工作。如果用不能真正地使值
//不changeable的‘true’进行调用,则实现应当提出异常。
//默认的实现在这些情况下返回true。
protected virtual bool MakeUnchangeableCore(bool checking);
//子类实现将改变进栈到在其上发生的事件处理程序
//(默认的实现是空的)。如果adding为true,
//则处理程序应当被添加到子-changeable上,否则应当如上所述地
//从它们移除。
protected virtual void PropagateEventHandler(EventHandler handler,bool adding);
//子类实现确认它们处在好的状态中。如果否,则抛出一个有意义的异常。
//这将在WritePostscipt()、EmbeddedChangeableWriter()上被调用。
//默认的实现是空的。
protected virtual void ValidateObjectState();
//当存在对值的改变时调用。默认的实现调用
//已注册的Changed处理程序。
protected virtual void OnChange();
//从任何从changeable读出嵌入的changeable的对象(读者)
//或将嵌入的changeable写入changeable的对象(写者)调用。
//它们的基本用途是属性设置和取得。见上面的例子。
protected Changeable EmbeddedChangeableReader(Changeableproperty);
   protected Changeable EmbeddedChangeableWriter(ChangeableoriginalChangeable,Changeable newChangeable);
//从简单的属性设置者和取得者,或者访问在Changeable上的
//非-Changeable状态的任何对象调用。见上面的例子。
protected void ReadPreamble();
protected void WritePreamble();
//从简单和复杂两者的属性设置者和其它在Changeable上
//设置状态的任何对象调用。见上面的例子。
protected void WritePostcript();
////静态帮助者方法
//创建所提供的Changeable的深的、不changeable的克隆,
//但在已经是不changeable的节点处停止(由于那些可以只通过
//分出对它们的引用来“克隆”)。如果传进null,则返回null
static protected Changeable CloneDownToUnchangeable(Changeablechangeable);
//使指定的Changeable是不可修改的(IsChangeable==false)
//并且当‘checking’参数是‘false’时返回true。否则,
//它检查以查看是否可以使该changeable成为不changeable的,按需要返回true
//或false。如果将null作为changeable传入,则这个操作不执行
//任何事情并返回‘true’。
static protected bool MakeUnchangeable(Changeable changeable,boolchecking);
}
//在ChangeableHelper.UseChangeable中使用UsageOverride
public enum ChangeableUsageOverride
{
NoOverride,//默认,用作指定的
ForceUnchangeable,//强制“使用”为不changeable的
PreferChangeableReference//如上所述。
}
//这个帮助者类存在以减少OM混乱出现在核心Changeable类型上。
public class System.Windows.ChangeableHelper
{
//HOSTING API。这是由系统而不是将作为这些值的主人的
//属性系统使用的。属性系统将使用这些入口点用于它们
//自己在WriteLocal中作宿主//通过获得对oldChangeable的改变的通知,移除处理程序
static public void UnsubscribeChangeable(Changeable changeable,EventHandler handlerToRemove);
//返回Changeable,添加处理程序以获得对它的改变的通知,
//如果有的话。注意,这是Changeable的“使用”,并且
//所返回的值将遵循“使用”的语义。如果“usageOverride”是
//NoOverride,如所希望的全部进行,如果它是
//“ForceUnchangeable”,则始终将Changeable
//视为StatusOfNextUse==UseStatus.Unchangeable。见上面的描述stalic public Changeable UseChangeable(Changeable changeable,
 EventHandler handlerToAssociate,
 ChangeableUsageOverride usageOverride);
}
注意,Changeable的受限制使用的行为,仅依赖于它的StatusOfNextUse,不完全在每种情况中工作。一般而言,问题是当changeable对象(诸如Brush、VideoData等)被赋值到Element属性中(象VideoSource),以受限制使用方式“使用”该changeable。在动画Changeable(诸如VideoData,但也可任何动画)的情况下,“使用”的行为创建克隆,它是正确和期望的行为。然后,当元素的OnRender()方法被调用时,OnRender()实现通常使值进栈到DrawingContext中,例如,通过DrawContext.DrawVideo(videoData,...)。这个调用到DrawingContext中还“使用”Changeable(在本例中为videoData),导致产生另一个克隆。
在孤立地考虑时,当以这种方式“使用”changeable时的两种行为都是正确和有意义的。然而,当它们组合时问题发生了,因为控件的实施者在每次调用OnRender()时不希望受限制的使用,并且实际上这么做没有好处,因为没有向应用揭示这种使用,而实际是应当消除的纯开销。而且,当依赖的动画和独立的动画组合时,将频繁地调用OnRender(),并且将反复地拷贝动画,这是不正确的行为。称为ChangeableReference的机制允许不实际拷贝的“使用”,但代之以只获得正在使用的引用。
解决方案是要具有在象DrawingContext的实体与在DependencyObject上的DependencyProperty之间的合作。特别地,控件的DependencyProperty,当将一个值设置给它时,需要表示它将“允许”Changeable被视为ChangeableReference,如果特定的上下文(随后被使用的)想要它这样。那么,DrawingContext操作假定表示它们“更喜欢”Changeable被视为ChangeableReference,假定Changeable本身将允许它。
为此,提供名为Changeable.AllowChangeableReferenceOverride的布尔属性和在ChangeableHelper.UseChangeable中使用的枚举项ChangeableUsageOverride。在这个实现中,UseChangeable象以前一样工作,并将true/false映射到ForceUnchangeable/NoOverride。如果用PreferChangeableReference调用UseChangeable并且changeable具有IsChangeable==true,并且changeable具有AllowChangeableReferenceOverride==true,则Changeable的使用将作为ChangeableReference。
这是通过让DependencyObject.SetValue()设置它已经保留了的Changeable为AllowChangeableReferenceOverride来使用这个,并且让DrawingContext方法用UsageOverridePreferChangeableReference来调用UseChangeable。
注意,当两个条件都不是true时,正确的行为也发生,因为Elt2.Prop=Elt1.Prop将如希望的以受限制的使用方式使用该属性,由于将不用PreferChangeableReference来调用UseChangeable。DrawingContext的直接用法也将适当地起作用,因为被向下发送到它的Changeable将不具有AllowChangeableReferenceOverride。
注意,当存在一个changeable其子对象是ChangeableReference时,可进行浅克隆和深克隆。浅克隆应当工作,因为CloneCore方法将创建一个新的浅“命令解释程序”,并且在子对象上赋值,而不深入到它们中。用深克隆,在ChangeableCopy和Unchangeable的树的情况中过程是直接的,通过向下克隆到Unchangeable,使沿路的每个克隆本身为Unchangeable(假设CanMakeUnchangeable为true)。这导致其中顶层为Changeable而之下的所有为Unchangeable的深克隆。注意,暂记将使子-元素再次可修改。
然而,当存在ChangeableReference时,克隆操作需要有效地执行,然而为“Changeable”路径向下至ChangeableReference保存一个引用。这是必要的,以便当存在来自ChangeableReference的通知时,在作为它的宿主的任何地方,正确的处理程序获得调用。
考虑下面的例子:
  Brush b=new LinearGradientBrush();
  b.Stops=new GradientStopCollection();
  GradientStop gs=new GradientStop();
  gs.StatusOfNextUse=UseStatus.ChangeableReference;
  b.Stops.Add(gs);
  Button button1,button2;
  button1.Background=b;
  button2.Background=b;(or button2.Background=button1.Background)
  gs.Color=Colors.Purple;
这里,创建LinearGradientBrush,以及它的Stop集合和一个单个的Stop,并且使之成为ChangeableReference。画刷可在多处使用,并且对ChangeableReference GradientStop的修改需要影响两个画刷。
使用changeable对象的例子(使无效有效)
下面的章节提供使用和操作从Changeable类派生的对象,通过它们,诸如画刷、笔和动画之类的对象是可变的,如由编程者控制。从Changeable派生的类通过在以受限制的使用方式使用时自动地建立它们的不可变版本来仿真可变性。如上所述,当对象被设置到属性系统属性中时,以受限制的使用方式使用Changeable,用作复杂Changeable对象中的子-对象,或者在DrawingContext命令中使用。
当用这样的对象开发应用时,创建、设置、使用并随后不再修改图形和媒体系统对象。例如,为设置Button的背景,编程者可能使用SolidColorBrush,它从Changeable派生;但编程者可能在应用的过程上从不再次修改按钮的背景。下面是一个例子:
 //C#
SolidColorBrush myBrush=new SolidColorBrush(Colors.Yellow);
myBrush.Opacity=0.5;
//myBrush的一次“使用”。
myButton.Background=myBrush;
     ’VB.NET
    Dim myBrush As new_
System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Yellow)
    myBrush.Opacity=0.5
    ’myBrush的使用。
    myButton.Background=myBrush
当以此方式使用时,Changeable像值类型诸如Rect或Color一样工作。将Changeable拷贝到它的目的地中,并且对原值的改变不影响对所使用值的改变。然而,存在编程者可能需要在使用这样一个对象之后要修改它的情况。例如,假设编程者想要在用户点击按钮之后改变在先前代码中的按钮的背景。
Changeable模式存在以满足各种各样情况诸如上述的情况的需求。通常,Changeable是一个可以或不可以改变的值,由IsChangeable属性的值来表示。当IsChangeable为false时试图修改值导致异常。而且,可以修改的IsChangeable对象当它们改变时或者当它们的任何成员被改变时提出它们的Changed事件。当用Changeable工作时,理解何时以受限制使用方式“使用”Changeable因而是重要的。
默认地,当以受限制使用方式使用Changeable对象时,创建不可变的拷贝并且实际使用该拷贝。该拷贝具有为false的IsChangeable值。下面的代码引起一个异常被抛出,因为该代码试图修改用于设置按钮的背景的myBrush的不可修改的拷贝。
 //C#
SolidColorBrush myBrush=new SolidColorBrush(Colors.Yellow);
myBrush.Opacity=0.5;
myButton.Background=myBrush;
//使一个异常被抛出
((SolidColorBrush)myButton.Background).Color=Colors.Blue;
        ’VB.NET
        Dim myBrush As new_
    System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Yellow)
        myBrush.Opacity=0.5
        myButton.Background=myBrush
        ’使一个异常被抛出
        CType(myButton.Background,
    System.Windows.Media.SolidColorBrush).Color=_
         System.Windows.Media.Colors.Blue
修改原来的Changeable对象不更新这些拷贝:
   //C#
    SolidColorBrush myBrush=new SolidColorBrush(Colors.Yellow);
    myBrush.Opacity=0.5;
    myButton.Background=myBrush;
    //不改变按钮的背景。
    myBrush.Color=Color.Blue;
     ’VB.NET
    Dim myBrush As new_
System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Yellow)
myBrush.Opacity=0.5
myButton.Background=myBrush
‘不改变按钮的背景。
myBrush.Color=System.Windows.Media.Colors.Blue
为改变本例中按钮的背景,编程者将修改过的画刷重新赋值给按钮的背景属性:
//C#
     SolidColorBrush myBrush=new SolidColorBrush(Colors.Yellow);
     myBrush.Opacity=0.5;
     myButton.Background=myBrush;
     //不改变按钮的背景。
     myBrush.Color=Color.Blue;
     //更新按钮的背景。myButton.Background=Colors.Blue;
     ’VB.NET
    Dim myBrush As new_
System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Yellow)
myBrush.Opacity=0.5
myButton.Background=myBrush
‘不改变按钮的背景。
 myBrush.Color=System.Windows.Media.Colors.Blue
‘更新按钮的背景。
 myButton.Background=myBrush
编程者还可以使用Copy方法来检索所使用的Changeable对象的可修改拷贝。所检索的拷贝仍被赋值回该属性以获得效果:
 //C#
SolidColorBrush myBrush=new SolidColorBrush(Colors.Yellow);
myBrush.Opacity=0.5
     myButton.Background=myBrush;
    SolidColorBrush notherBrush=(SolidColorBrush)myButton.Background.Copy();
    anotherBrush.Color=Colors.Purple;
    //更新按钮的背景。
    myButton.Background=anotherBrush;
     ’VB.NET
    Dim myBrush As new_
System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Yellow)
    myBrush.Opacity=0.5
    myButton.Background=myBrush
    Dim anotherBrush As new System.Windows.Media.SolidColorBrush
    anotherBrush=_
     CType(myButton.Background.Copy,
System.Windows.Media.SolidColorBrush)
    anotherBrush.Color=System.Windows.Medial.Colors.Purple
    ‘更新按钮的背景。
     myButton.Background=anotherBrush
因为这不是一个Changeable在所有情况下的理想行为,例如,考虑编程者想要修改该Changeable的所使用版本(工作拷贝),该Changeable类使编程者能够指定当通过提供StatusOfNextUse属性使用时它如何工作。
StatusOfNextUse提供Changeable在被使用时如何工作的三个选项:
Unchangeable:默认的行为,在前面章节的例子示出。当使用Changeable对象时,它创建它在原地使用的原对象本身的不可变拷贝。编程者可继续修改原对象;所使用的版本(所产生的拷贝)不受对原对象的修改的影响,并且不能被修改。为修改所使用的版本,使用Copy方法来获得可修改版本,更新该版本,并且新版本代替所使用的版本。
ChangeableCopy:当使用Changeable对象时,它创建在原地使用的原对象本身的可修改拷贝。编程者可继续修改原对象;所使用的版本(所产生的拷贝)不受对原对象修改的影响,但也是可修改的。所使用的版本具有为Unchangeable的StatusOfNextUse。
ChangeableReference:当使用Changeable对象时,它提供到它自己的引用。编程者可继续修改原对象;对原对象的改变影响所使用的版本--它们是同一对象。
ChangeableCopy改变Changeable的行为,以便当被使用时它创建它本身的可修改拷贝,而不是不可修改拷贝(好象具有默认设置为Unchangeable的情况)。下面的代码(先前示出的)抛出一个异常,因为myBrush的StatusOfNextUse属性具有为Unchangeable的默认设置:
//C#
SolidColorBrush myBrush=new SolidColorBrush(Colors.Yellow);
myBrush.Opacity=0.5;
myButton.Background=myBrush;
//使一个异常被抛出。
((SolidColorBrush)myButton.Background).Color=Color.Blue;
‘VB.NET
Dim myBrush As new_
System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Yellow)
myBrush.Opacity=0.5
myButton.Background=myBrush
‘使一个异常被抛出。
    CType(myButton.Background,
System.Windows.Media.SolidColorBrush).Color=_
    System.Windows.Media.Color.Blue
然而,如果画刷的StatusOfNextUse设置为ChangeableCopy,则代码如所想地工作:
     //C#
    SolidColorBrush myBrush=new SolidColorBrush(Colors.Yellow);
    myBrush.StatusOfNextUse=UseStatus.ChangeableCopy;
    myBrush.Opacity=0.5;
    myButton.Background=myBrush;
    //工作,因为画刷具有为ChangeableCopy的UseStatus。
    ((SolidColorBrush)myButton.Background).Color=Color.Blue;
    ‘VB.NET
    Dim myBrush As new_
    System.Windows.Media.SolidColorBrush(System.Windows.Media.Color
s.Yellow)
    myBrush.StatusOfNextUse=MSAvalon.Windows.UseStatus.ChangeableCo
py
    myBrush.Opacity=0.5
    myButton.Background=myBrush
    ‘工作,因为画刷具有为ChangeableCopy的UseStatus。
    CType(myButton.Background,
System.Windows.Media.SolidColorBrush).Color=_
     System.Windows.Media.Color.Blue
    ChangeableCopy设置还使主对象的任何子-对象保持可修改。在下面的例子中,将为ChangeableCopy的StatusOfNextUse给以LinearGradientBrush。结果,LinearGradientBrush及其子-对象在已经使用它们之后保持可修改;编程者不必设置由该对象包含的任何Changeable对象诸如本例中的
GradientStop的StatusOfNextUse属性:
    //C#
    LinearGradientBrush myBrush=new LinearGradientBrush();
    myBrush.StatusOfNextUse=UseStatus.ChangeableCopy;
    myBrush.GradientStops.Add(new GradientStop(Colors.Blue,0));
    myBrush.GradientStops.Add(new GradientStop(Colors.Green,1));
    myButton.Background=myBrush;
    //工作,因为画刷具有为ChangeableCopy的UseStatus。
    ((LinearGradientBrush)myButton.Background).GradientStops[0].Col
or=
    Colors.LightBlue;
    ‘VB.Net
    Dim myBrush As new System.Windows.Media.LinearGradientBrush
    myBrush.StatusOfNextUse=MSAvalon.Windows.UseStatus.ChangeableCo
py
    myBrush.GradientStops.Add(_
     new System.Windows.Media.GradientStop(System.Windows.Media.
Colors.Blue,0))
    myBrush.GradientStops.Add(new_
    System.Windows.Media.GradientStop(System.Windows.Media.Colors.G
reen,1))
    myButton.Background=myBrush;
     //工作,因为画刷具有为ChangeableCopy的UseStatus。
    CType(myButton.Background_
    System.Windows.Media.LinearGradientBrush).GradientStops(0).Color=_
     System.Windows.Media.Colors.LightBlue
当使用具有为ChangeableCopy的StatusOfNextUse的Changeable对象时,编程者也可以保留Changeable的所使用版本的句柄,并且使用该引用来修改该对象。在下面的例子中,检索到所使用的LinearGradientBrush的引用并且用它修改按钮的背景:
     //C#
    LinearGradientBrush myBrush=new LinearGradientBrush();
    myBrush.StatusOfNextUse=UseStatus.ChangeableCopy;
    myBrush.GradientStops.Add(new GradientStop(Colors.Blue,0));
    myBrush.GradientStops.Add(new GradientStop(Colors.Green,1));
    myButton.Background=myBrush;
    LinearGradientBrush usedBrush=(LinearGradientBrush)myButton.
Background;
     //工作,因为画刷具有为ChangeableCopy的UseStatus。
    usedBrush.GradientStops[0].Color=
    Colors.LightBlue;
    ‘VB.NET
    Dim myBrush As new System.Windows.Media.LinearGradientBrush
    myBrush.StatusOfNextUse=MSAvalon.Windows.UseStatus.ChangeableCo
py
    myBrush.GradientStops.Add(_
     new
System.Windows.Media.GradientStop(System.Windows.Media.Colors.Blue,
0))
    myBrush.GradientStops.Add(_
     new
System.Windows.Media.GradientStop(System.Windows.Media.Colors.Green
,1))
    myButton.Background=myBrush;
    Dim usedBrush As new System.Windows.Media.LinearGradientBrush
    usedBrush=Ctype(myButton.Background,LinearGradientBrush)
     //工作,因为画刷具有为ChangeableCopy的UseStatus。
    usedBrush.GradientStops(0).Color=_
     System.Windows.Media.Colors.LightBlue
    ChangeableReference设置改变Changeable的行为,因此它在被使用时提供到它自己的引用。编程者可继续修改原对象;对原对象的改变影响所使用版本,因为它们是同一对象。下面是一个例子:
    //VB.NET
    SolidColorBrush changeableReferenceBrush=new SolidColorBrush();
    changeableReferenceBrush.Color=Colors.LimeGreen;
    button1.Background=changeableReferenceBrush;
    button2.Background=changeableReferenceBrush;
    button3.Background=changeableReferenceBrush;
    //改变三个按钮的颜色。
    changeableReferenceBrush.Color=Color.Purple;
    //也改变所有三个按钮的颜色。
    ((SolidColorBrush)button1.Background).Color=Colors.Blue;
     ‘C#
     Dim changeableReferenceBrush As new
System.Windows.Media.SolidColorBrush
     changeableReferenceBrush.Color=System.Windows.Media.Colors.Lime
Green
    button1.Background=changeableReferenceBrush
    button2.Background=changeableReferenceBrush
    button3.Background=changeableReferenceBrush
    //改变三个按钮的颜色。
    changeableReferenceBrush.Color=System.Windows.Media.Color.Purpl
e
    //也改变所有三个按钮的颜色。
    CType(button1.Background,
    System.Windows.Media.SolidColorBrush).Color=_
    System.Windows.Media.Colors.Blue
画刷和笔
画刷是表示填充平面的方法的对象。除了能够以绝对方式填充平面之外,媒体集成层的画刷还能够相对它们正在填充的对象的尺寸来调节如何填充平面。画刷类型的例子包括SolidColorBrush、VisualBrush(它可以引用Visual)、DrawingBrush(它可以引用向量图形资源)、LinearGradient、RadialGradient、ImageBrush和NineGridBrush。下面描述画刷属性的默认值,并且通常是不导致动作的值。即,颜色默认为透明的,等等。而且,动画集合默认为null。
如上面提到的,某些画刷对象具有它们在被使用时如何相关于坐标系统的概念,以及它们在被使用时如何相关于几何图形的边界框的概念。这个尺寸基于来自画刷正在填充的对象。
Brush基类具有Transform、一般不透明性和混合模式:
public abstract class System.Windows.Media.Brush:Changeable
{
 internal Brush();
 public new Brush Copy();//隐藏Changeable.Copy()
 //默认为Transform.Identity
public Transform Transform{get;set;}
 [Animation(″OpacityAnimations″)]
 public double Opacity{get;set;}//默认为1.0
 public DoubleAnimation Collection Opacity Animations{get;set;}
 ///当被绘制时,BlendMode应用于这个Brush及其目的地。
 ///默认为BlendModes.Normal
 public BlendMode BlendMode{get;set;}
}
Brush(以及在向量图形和MIL API中的其它对象资源)对象是Changeable并且在创建它们之后是可写的,而且遵循一般的Changeable模式,即以受限制使用方式使用它们之后它们如何工作。
Brush(除了VisualBrush和DrawingBrush之外)具有以标记方式使用的简单句法,然而,这种简单句法不允许访问所有的属性和行为。如果编程者需要比简单句法所提供的更多的访问,则编程者将需要使用复杂句法。注意,这里只给出简单句法以避免冗余,因为复杂句法遵循与其它CLR类相同的模式。
下面是具有在当前实现中用于标记的简单句法的画刷类型:
brush:
 solid-color-brush|
 linear-gradient-brush|
 radial-gradient-brush|
 image-brush|
 video-brush|
 nine-grid-brush
许多画刷类型使用坐标系统用于指定它们的某些参数。这个坐标系统可以定义为相对于该画刷所用于的几何图形的简单边界框,或者它可以是绝对的,并且在使用该画刷时活动的坐标空间中解释它。这些分别被称为RelativeToBoundingBox和Absolute模式。
public enum System.Windows.Media.BrushMappingMode
{
 Absolute,
 RelativeToBoundingBox,
}
SolidColorBrush用纯色填充平面。如果存在颜色的alpha分量,则以乘法方法用Brush中相应的不透明性属性组合它。
public sealed class System.Windows.Media.SolidColorBrush:Brush
{
 //构造函数
 public SolidColorBrush();//初始化为透明
 public SolidColorBrush(Color color);
 public new SolidColorBrush Copy();//隐藏Changeable.Copy()
 //默认为透明的
 [Animation(″ColorAnimations″)]
 public Color Color{get;set;}
 public ColorAnimationCollection ColorAnimations{get;set;}
}
因为这是简单类型,(即,它的属性都不是Changeable),所以需要实现的受保护方法只有CloneCore()。而且,由于不存在使这个对象无效的值组合,因此没有必要提供ValidateObjectState()方法。这些方法和其它有关方法在附录中描述。
用于SolidColorBrush的标记的简单句法:
solid-color-paint:
 color
Brush类包含用于被揭示的SolidColorBrush实例的静态属性。这个属性设置为相同名称的颜色值。注意,因为这些是标准化的画刷,它们具有设置为false的IsChangeable,(例如,该实现在构造时调用MakeUnchangeable())。
下面阐述某些标准颜色:
public sealed class Brushes
{
  public static SolidColorBrush AliceBlue{get;}
  public static SolidColorBrush AntiqueWhite{get;}
public static SolidColorBrush Aqua{get;}
public static SolidColorBrush Aquamine{get;}
public static SolidColorBrush Azure{get;}
public static SolidColorBrush Beige{get;}
public static SolidColorBrush Bisque{get;}
public static SolidColorBrush Black{get;}
public static SolidColorBrush BlanchedAlmond{get;}
public static SolidColorBrush Blue{get;}
public static SolidColorBrush BlueViolet{get;}
public static SolidColorBrush Brown{get;}
public static SolidColorBrush BurlyWood{get;}
public static SolidColorBrush CadetBlue{get;}
public static SolidColorBrush Chartreuse{get;}
public static SolidColorBrush Chocolate{get;}
public static SolidColorBrush Coral{get;}
public static SolidColorBrush CornflowerBlue{get;}
public static SolidColorBrush Cornsilk{get;}
public static SolidColorBrush Crirnson{get;}
public static SolidColorBrush Cyan{get;}
public static SolidColorBrush DarkBlue{get;}
public static SolidColorBrush DarkCyan{get;}
public static SolidColorBrush DarkGoldenrod{get;}
public static SolidColorBrush DarkGray{get;}
public static SolidColorBrush DarkGreen{get;}
public static SolidColorBrush DarkKhaki{get;}
public static SolidColorBrush DarkMagenta{get;}
public static SolidColorBrush DarkOliveGreen{get;}
public static SolidColorBrush DarkOrange{get;}
public static SolidColorBrush DarkOrchid{get;}
public static SolidColorBrush DarkRed{get;}
public static SolidColorBrush DarkSalmon{get;}
public static SolidColorBrush DarkSeaGreen{get;}
public static SolidColorBrush DarkSlateBlue{get;}
public static SolidColorBrush DarkSlateGray{get}
public static SolidColorBrush DarkTurquoise{get;}
public static SolidColorBrush DarkViolet{get;}
public static SolidColorBrush DeepPink{get;}
public static SolidColorBrush DeepSkyBlue{get;}
public static SolidColorBrush DirnGray{get;}
public static SolidColorBrush DodgerBlue{get;}
public static SolidColorBrush Firebrick{get;}
public static SolidColorBrush FloblWhite{get;}
public static SolidColorBrush ForestGreen{get;}
public static SolidColorBrush Fuchsia{get;}
public static SolidColorBrush Gainsboro{get;}
public static SolidColorBrush GhostWhite{get;}
public static SolidColorBrush Gold{get;}
public static SolidColorBrush Goldenrod{get;}
public static SolidColorBrush Gray{get;}
public static SolidColorBrush Green{get;}
public static SolidColorBrush GreenYellow{get;}
public static SolidColorBrush Honeydew{get;}
public static SolidColorBrush HotPink{get;}
public static SolidColorBrusb IndianRed{get;}
public static SolidColorBrush Indigo{get;}
public static SolidColorBrush Ivory{get;}
public static SolidColorBrush Khaki{get;}
public static SolidColorBrush Lavender{get;}
public static SolidColorBrush LavenderBlush{get;}
public static SolidColorBrush LawnGreen{get;}
public static SolidColorBrush LernonChiffon{get;}
public static SolidColorBrush LightBlue{get;}
public static SolidColorBrush LightCoral{get;}
public static SolidColorBrush LightCyan{get;}
public static SolidColorBrush LightGoldenrodYellow{get;}
public static SolidColorBrush LightGray{get;}
public static SolidColorBrush LightGreen{get;}
public static SolidColorBrush LightPink{get;}
public static SolidColorBrush LightSalmon{get;}
public static SolidColorBrush LightSeaGreen{get;}
public static SolidColorBrush LightSkyBlue{get;}
public static SolidColorBrush LightSlateGray{get;}
public static SolidColorBrush LigbtSteelBlue{get;}
public static SolidColorBrush LightYellow{get;}
public static SolidColorBrush Lime{get;}
public static SolidColorBrush LimeGreen{get;}
public static SolidColorBrush Linen{get;}
public static SolidColorBrush Magenta{get;}
public static SolidColorBrush Maroon{get;}
public static SolidColorBrush MediumAquamarine{get;}
public static SolidColorBrush MediumBlue{get;}
public static SolidColorBrush MediumOrchid{get;}
public static SolidColorBrush MediumPurple{get;}
public static SolidColorBrush MediumSeaGreen{get;}
public static SolidColorBrush MediumSlateBlue{get;}
public static SolidColorBrush MediumSpringGreen{get;}
public static SolidColorBrush MediumTurquoise{get;}
public static SolidColorBrush MediumVioletRed{get;}
public static SolidColorBrush MiduightBlue{get;}
public static SolidColorBrush MintCream{get;}
public static SolidColorBrush MistyRose{get;}
public static SolidColorBrush Moccasin{get;}
public static SolidColorBrush NavajoWhite{get;}
public static SolidColorBrush Navy{get;}
public static SolidColorBrush OldLace{get;}
public static SolidColorBrush Olive{get;}
public static SolidColorBrush OliveDrab{get;}
public static SolidColorBrush Orange{get;}
public static SolidColorBrush OrangeRed{get;}
public static SolidColorBrush Orchid{get;}
public static SolidColorBrush PaleGoldenrod{get;}
public static SolidColorBrush PaleGreen{get;}
public static SolidColorBrush PaleTurquoise{get;}
public static SolidColorBrush PaleVioletRed{get;}
public static SolidColorBrush PapayaWhip{get;}
public static SolidColorBrush PeachPuff{get;}
public static SolidColorBrush Peru{get;}
public static SolidColorBrush Pink{get;}
public static SolidColorBrush Plurn{get;}
public static SolidColorBrush PowderBlue{get;}
public static SolidColorBrush Purple{get;}
public static SoiidColorBrush Red{get;}
public static SolidColorBrush RosyBrown{get;}
public static SolidColorBrush RoyalBlue{get;}
public static SolidColorBrush SaddleBrown{get;}
public static SolidColorBrush Salrnon{get;}
public static SolidColorBrush SandyBrown{get;}
public static SolidColorBrush SeaGreen{get;}
public static SolidColorBrush SeaShell{get;}
public static SolidColorBrush Sienna{get;}
public static SolidColorBrush Silver{get;}
public static SolidColorBrush SkyBlue{get;}
public static SolidColorBrush SlateBlue{get;}
public static SolidColorBrush SlateGray{get;}
public static SolidColorBrush Snow{get;}
public static SolidColorBrush SpringGreen{get;}
public static SolidColorBrush SteelBlue{get;}
public static SolidColorBrush Tan{get;}
  public static SolidColorBrush Teal{get;}
  public static SolidColorBrush Thistle{get;}
  public static SolidColorBrush Tomato{get;}
  public static SolidColorBrush Transparent{get;}
  public static SolidColorBrush Turquoise{get;}
  public static SolidColorBrush Violet{get;}
  public static SolidColorBrush Wheat{get;}
  public static SolidColorBrush White{get;}
  public static SolidColorBrush WhiteSmoke{get;}
  public static SolidColorBrush Yellow{get;}
  public static SolidColorBrush YellowGreen{get;}
}
通过指定一组渐变停止符来绘制渐变.这些渐变停止符沿某种进程指定颜色。存在两种目前支持的渐变类型,即线性和径向渐变。渐变是通过在指定颜色空间中进行渐变停止符之间内插来绘制的。
渐变是由一列渐变停止符组成的。这些渐变停止符的每一个包含颜色(连同包括的alpha值)和偏移。如果不存在指定的渐变停止符,则透明地绘制画刷(好象不存在指定的画刷)。如果只存在一个指定的渐变停止符,则按具有指定的一种颜色的纯色来绘制画刷。考虑任何具有在零到一(0.0...1.0)的范围内的偏移的渐变停止符,连同在范围(-∞...0.0)内的最大停止符和在范围[1.0...∞]内的最小停止符。如果所考虑的停止符集合包括在范围零到一之外的停止符,则在零(和/或一)处得到一个隐含的停止符,代表在这个停止符处将出现的内插颜色。而且,如果在同一偏移处设置两个或多个停止符,在该偏移处将出现硬过渡(而不是内插的)。添加停止符的顺序决定在这个偏移处的行为;要添加的第一停止符是在该偏移之前的有效颜色,要设置的最后一个停止符是在这个停止符之后的有效颜色,并且忽略在这个偏移处的任何附加停止符。
这个类像其它资源类一样是Changeable:
public sealed class System.Windows.Media.GradientStop:Changeable
{
  public GradientStop();
 public Gradi entStop(Color color,double offset);
 public GradientStop(Color color,ColorAnimationCollectioncolorAnimation,
 double offset,DoubleAnimationCollection offsetAnimation);
 public new GradientStop Copy();//隐藏Changeable.Copy()
 //默认为透明
 [Animation(″ColorAnimations″)]
 public Color Color{get;set;}
 public ColorAnimationCollection ColorAnimations{get;set;}
 //默认为0
 [Animation(″OffsetAnimations″)]
 public double Offset{get;set;}
 public DoubleAnimationCollection OffsetAnimations{get;set;}
}
象SolidColorBrush一样,这在动画集合中具有嵌套的Changeable。
GradientSpreadMethod枚举指定应当如何在指定的向量或空间之外绘制渐变。存在三个可能值,包括Pad,其中使用末端颜色(第一个和最后一个)填充剩余的空间,Reflect,其中以相反的顺序反复地重放这些停止符以填充空间,以及Repeat,其中按顺序重复这些停止符,直到填充了空间为止。这个类型的属性的默认值是Pad:
public enum System.Windows.Media.GradientSpreadMethod
{
 Pad,
 Reflect,
 Repeat
}
图24提供某些GradientSpreadMethod例子,(虽然是以灰度而不是以颜色)。每种形状具有从白色到灰色的线性渐变。实线表示渐变向量。
ColorInterpolationMode枚举定义在渐变内颜色的内插模式。两个选项是PhysicallyLinearGamma和PerceptuallyLinearGamma。
public enum ColorInterpolationMode
{
//在Gamma 1.0空间中内插颜色
PhysicallyLinearGamma,
//在Gamma 2.2空间中内插颜色
PerceptuallyLinearGamma
}
这是一个抽象基类。
public abstract class System.Windows.Media.GradientBrush:Brush
{
 internal GradientBrush();
 public new GradientBrush Copy();//隐藏Changeable.Copy()
 //默认为“PerceptuallyLinearGamma”
 public ColorInterpolationMode ColorInterpolationMode{get;set;}
 //默认为RelativeToBoundingBox
 public BrushMappingMode MappingMode{get;set;}
 //默认为Pad
 public GradientSpreadMethod SpreadMethod{get;set;}
 //渐变停止符
 public void AddStop(Color color,double offset);
 public GradientStopCollection GradientStops{get;set;}
 //ColorInterpolationMode
 public ColorIntepolationMode ColorInterpolationMode{get;set;}
}
LinearGradient指定沿一向量的线性渐变画刷。各个停止符指定沿该向量的颜色停止符。
public sealed class System.Windows.Media.LinearGradient:Gradient
{
 public LinearGradient();//初始化为透明
 //用两种颜色和一个渐变向量来建立渐变,
 //它们被专用于填充要应用该渐变的对象。
 //这隐含着GradientUnits属性的RelativeToBoundingBox
 public LinearGradient(Color color1,Color color2,double angle);
 public LinearGradient(Color color1,Color color2,
  Point vectorStart,Point vectorEnd);
 public new LinearGradient Copy();//隐藏Changeable.Copy()
 //渐变向量起点
 //默认为0,0
 [Animation(″StartPointAnimations″)]
 public Point StartPoint{get;set;}
 public PointAnimationCollection StartPointAnimations{get;set;}
 //默认为1,1
 [Animation(″EndPointAnimations″)]
 public Point EndPoint{get;set;}
 public PointAnimationCollection EndPointAnimations{get;set;}
}
用于LinearGradientBrush的标记的简单句法:
linear-gradient-brush:
 ″HorizontalGradient″comma-wsp color comma-wsp color|
 ″VerticalGradient″comma-wsp color comma-wsp color|
 ″LinearGradient″comma-wsp coordinate-pair comma-wsp colorcomma-wsp color
LinearGradient的标记允许用在偏移零或一处的两个颜色停止符来指定LinearGradient。如果使用“LinearGradient”版本,则分别指定起点和终点。如果用“HorizontalGradient”则起点设置为0,0而终点设置为1,0。如果使用“VerticalGradient”则起点设置为0,0而终点设置为0,1。在这些情况下,使用默认的MappingMode,它是RelativeToBoundingBox。
RadialGradient在编程模型中与线性渐变相似。然而,尽管线性渐变具有定义渐变向量的起点和终点,但径向渐变具有一个圆连同一个焦点来定义渐变行为。该圆定义渐变的终点一换言之,在1.0处的渐变停止符定义在圆的圆周处的颜色。焦点定义渐变的中心。在0.0处的渐变停止符定义焦点处的颜色。图25代表(以灰度方式)从白色变到灰色的RadialGradient。外面的圆代表渐变圆,而实点子表示焦点。这个渐变具有设置为Pad的SpreadMethod。
    public                sealed                              class
System.Windows.Media.RadialGradient:GradientBrush
    {
     public RadialGradient();//初始化为透明
     //设置具有两种颜色的渐变。
     //这隐含着GradientUnits属性的RelativeToBoundingBox
     //连同在(0.5,0.5)处的中心
     //0.5的半径和在(0.5,0.5)处的焦点
     public RadialGradient(Color color1,Color color2);
     public new RadialGradient Copy();//隐藏Changeable.Copy()
     //默认为0.5,0.5
     [Animation(″CenterAnimations″)]
     public Point Center{get;set;}
     public PointAnimationCollection CenterAnimations{get;set;}
     //默认为0.5
     [Animation(″RadiusXAnimations″)]
     public double RadiusX{get;set;}
     public DoubleAnimationCollection RadiusXAnimations{get;set;}
 //默认为0.5
 [Animation(″RadiusYAnimations″)]
 public double RadiusY{get;set;}
 public DoubleAnimationCollection RadiusYAnimations{get;set;}
 //默认为0.5,0.5
 [Animation(″FocusAnimations″)]
 public Point Focus{get;set;}
 public PointAnimationCollection FocusAnimations{get;set;}
}
RadialGradient的标记允许用分别在偏移0和1处的两种颜色停止符来指定RadialGradient。使用默认的MappingMode,它是RelativeToBoundingBox,而默认的半径为0.5:
radial-gradient-brush:
 ″RadialGradient″comma-wsp color comma-wsp color
TileBrush是一个抽象基类,它包含描述平铺和该平铺应当填充一个区域时所通过的方法的逻辑。TileBrush的子类包含内容,并且逻辑地定义填充无限平面的方法。
Stretch枚举用于描述如何将ViewBox(源坐标空间)映射到ViewPort(目的地坐标空间)。在TileBrush中使用它:
public enum System.Windows.Stretch
{
 //保持原尺寸
 None,
 //不保持纵横比,ViewBox填充ViewPort
 Fill,
 //保持纵横比,尽可能大地一致地缩放ViewBox,
 //使得宽和高都适配在ViewPort内
 Uniform,
 //保持纵横比,尽可能小地一致地缩放ViewBox,
 //使得整个ViewPort由ViewBox填充
 UniformToFill,
}
图26提供拉伸例子。在这些例子中,内容是上/左对齐的。
TileMode枚举用于描述是否由Tile填充空间和如何填充。TileBrush定义基Tile在何处(由ViewPort指定)。基于TileMode值填充空间的其余部分。
public enum System.Windows.Media.TileMode
{
 //不平铺--只绘制基平铺,剩余区域保持透明
 None,
 //基本平铺模式--绘制基平铺并且通过重复基平铺填充剩余区域,
 //使得一个平铺的右边缘平接下一个的左边缘,并且下面和上面一样
 Tile,
 //与平铺一样,但垂直地翻转平铺的交替列。
 //无变换地绘制基平铺。
 FlipX,
 //与平铺一样,但水平地翻转平铺的交替行。
 //无变换地绘制基平铺。
 FlipY,
 //FlipX和FlipY的组合。无变换地绘制基平铺
 FlipXY
}
图27提供TileMode例子。在每个例子中的最上左的平铺是基平铺。这些例子代表None,Tile,FlipX,FlipY和FlipXY。
VerticalAlignment枚举用于描述如何将内容垂直地放置在容器内:
public enum System.Windows.VerticalAlignment
{
 //将内容与空间上面对齐
 Top,
 //中心内容垂直地
 Center,
 //将内容与空间下面对齐
 Bottom,
}
HorizontalAlignment枚举用于描述如何水平地将内容放置在容器内。
public enum System.Windows.HorizontalAlignment
{
 //将内容向空间的左边对齐
 Left,
 //水平地使内容在中间
 Center,
 //将内容向空间的右边对齐
 Right,
}
TileBrush属性选择要成为平铺(ViewBox)的无限平面的矩形部分,并且描述将成为正在填充的区域中的基Tile的目的地矩形。剩余的目的地区域将基于TileMode属性来填充,它控制是否和如何将原平铺复制以填充剩余空间:
public abstract class System.Windows.Media.TileBrush:Brush
{
 public new TileBrush Copy();//隐藏Brush.Copy()
 //默认为RelativeToBoundingBox
 public BrushMappingMode ViewPortUnits{get;set;}
 //默认为RelativeToBoundingBox
 public BrushMappingMode ContentUnits{get;set;}
 //默认为Rect.Empty
 [Animation(″ViewBoxAnimations″)]
 public Rect ViewBox{get;set;}
 public RectAnimationCollection ViewBoxAnimation{get;set;}
 //默认为Fill
 public Stretch Stretch{get;set;}
 //默认为None
 public TileMode TileMode{get;set;}
 //默认为Center
 public HorizontalAlgnment HorizontalAlignment{get;set;}
  //默认为Center
 public VerticalAlignment VerticalAlignment{get;set;}
 //默认为0,0,1,1
 [Animation(″ViewPortAnimation″)]
 public Rect ViewPort{get;set;}
 public RectAnimationCollection ViewPortAnimations{get;set;}
}
TileBrush的内容没有固有的边界,并且实际上描述无限平面。这些内容存在于它们自己的坐标空间中,并且由TileBrush填充的空间是在应用时的局部坐标空间。基于ViewBox、ViewPort、Alignments和Stretch属性将内容空间映射到局部空间中。ViewBox在内容空间中指定,并且将这个矩形映射到ViewPort矩形中。
ViewPort定义内容将最终被绘制的位置,创建这个Brush的基平铺。如果ViewPortUnits的值是Absolute,则ViewPort的值被认为在应用时的局部空间中。如果,代之以ViewPortUnits的值是RelativeToBoundingBox,则ViewPort的值被认为在坐标空间中,其中0,0是正在绘画的对象的边界框的上/左角而1,1是同一边框的下/右角。例如,考虑正在填充的RectangleGeometry从100,100绘制到200,200。那么,如果ViewPortUnits是Absolute,则(100,100,100,100)的ViewPort将描述整个内容区域。如果ViewPortUnits是RelativeToBoundingBox,则(0,0,1,1)的ViewPort将描述整个内容区域。如果ViewPort的Size为空,并且Stretch不是None,则这个Brush没有内容呈现。
在内容空间中指定ViewBox。这个矩形被变换成适配在ViewPort内,如由Alignment属性和Stretch属性确定的。如果Stretch是None,则没有缩放应用于内容。如果Stretch是Fill,则在两个X和Y方向上独立地缩放ViewBox到与ViewPort相同的尺寸。如果Stretch是Uniform或UniformToFill,则逻辑是相似的,但X和Y维是均匀地缩放的,保持内容的纵横比。如果Stretch是Uniform,则ViewBox被缩放到具有等于ViewPort的尺寸的较大受约束的维。如果Stretch是UniformToFill,则ViewBox被缩放到具有等于ViewPort尺寸的较小受约束的维。考虑这个的另一种方法是Uniform和UniformToFill两者保持纵横比,但Uniform保证整个ViewBox在ViewPort内(有可能留下不被ViewBox覆盖的部分ViewPort),而UniformToFill保证整个ViewPort被ViewBox填充(有可能使部分ViewBox在ViewPort之外)。如果ViewBox的区域为空,则不应用Stretch。对齐仍将发生,并且它将放置“点”ViewBox。
一旦确定了ViewPort(基于ViewPortUnits)和确定了ViewBox的目的地尺寸(基于Stretch),ViewBox就需要被放置在ViewPort内。如果ViewBox与ViewPort是相同的尺寸(如果Stretch是Fill,或者如果它只碰巧出现其它三个Stretch值之一),则ViewBox被放置在原点,以便与ViewPort相同。如果否,则考虑HorizontalAlignment和VerticalAlignment。基于这些属性,在X和Y维上都对齐ViewBox。如果HorizontaiAlignment是Left,则ViewBox的左边缘将被放置在ViewPort的左边缘。如果是Center,则ViewBox的中央将放置在ViewPort的中央,且如果是Right,则右边缘将接合。对Y维重复这个过程。
如果ViewBox是空,则认为它未设置。如果它未被设置,则考虑ContentUnits。如果ContentUnits是Absolute,则没有缩放或偏移发生,并且无变换地将内容绘制到ViewPort中。如果ContentUnits是RelativeToBoundingBox,则内容原点与ViewPort原点对齐,并且按对象的边界框的宽度和高度缩放内容。
当用tileBrush填充空间时,如上所述地将内容映射到ViewPort中,并且剪辑成ViewPort。这形成用于填充的基平铺,并且基于Brush的TileMode填充剩余的空间。如果设置,则应用Brush的变换,它在其它映射、缩放、偏移等等之后发生。
VisualBrush是由Visual指定其内容的TileBrush。这个Brush可以用于创建复杂的图案,或者它可以用于绘制其它部分场景的内容的附加拷贝。
public sealed class System.Windows.Media.VisualBrush:TileBrush
{
 public VisualBrush();//初始化为透明
 public VisualBrush(Visual v);
 public new VisualBrush Copy();//隐藏TileBrush.Copy()
 //Visual--默认为null(透明Brush)
 public Visual Visual{get;set;}
}
如提到的,VisualBrush没有用于标记的简单句法,尽管它可以通过复杂句法来描述。
DrawingBrush是由Drawing指定其内容的TileBrush。这个Brush可以用于创建通过DrawingContext创建的复杂图案。
public sealed class System.Windows.Media.DrawingBrush:TileBrush
{
 public DrawingBrush();//初始化为透明
 public DrawingBrush(Drawing drawing);
 public new DrawingBrush Copy();//隐藏TileBrush.Copy()
 //Drawing--默认为null(透明Brush)
 public Drawing Drawing{get;set;}
}
如提到的,DrawingBrush没有用于标记的简单句法,尽管它可以通过复杂句法来描述。
ImageBrush是具有由ImageSource指定的内容的TileBrush。这个Brush可以用于用图象来填充空间。
public sealed class System.Windows.Media.ImageBrush:TileBrush
{
 public ImageBrush();//初始化为透明内容
 //设置图象,设置ViewBox到(0,0,Width,Height)
 //并且设置Stretch为Fill
 public ImageBrush(ImageData image);
 public new ImageBrush Copy();//隐藏TileBrush.Copy()
 //默认为null
 public ImageSource ImageSource{get;set;}
 //默认为true
 //如果它是true,则ViewBox属性将被覆盖
 //并且被设置为图象的原来尺寸
 public bool SizeViewBoxToContent{get;set;}
}
ImageBrush的用于标记的简单句法:
image-brush:
 ″Image″image-uri
VideoBrush是具有由VideoData指定的内容的TileBrush。这个Brush可以用于用视频填充空间。
public sealed class System.Windows.Media.VideoBrush:TileBrush
{
 public VideoBrush();//初始化为透明内容
 //设置图象,设置ViewBox到(0,0,Width,Height)
 //并且设置Stretch为Fill
 public VideoBrush(VideoData video);
 public new VideoBrush Copy();//隐藏TileBrush.Copy()
 //默认为null
 public VideoData VideoData{get;set;}
 //默认为true
 //如果它是true,则ViewBox属性将被覆盖
 //并且被实际上设置为视频的原来尺寸
 public bool SizeViewBoxToContent{get;set;}
}
VideoBrush的用于标记的简单句法:
video-brush:
 ″Video″video-uri
NineGridBrush是始终用它的内容图象填充对象边界框的Brush,并且图象拉伸不是纯粹通过视件缩放来完成。图象源被四条边划分成九个矩形(因此名为NineGrid)。在那些九个区域的每一个中图象的内容在0,1,2维上缩放,直到它们填充对象边界框为止。可以图28这个图中看到的在其中每个部分被缩放的维代表NineGrid的概念,示出由上、左、下和右边定义的九个栅格。在每个栅格方形中的箭头示出其中那些内容将被拉伸成符合ViewPort尺寸的维。
除了上面示出的九个栅格区域,存在一个可选的“第十”个栅格。这用附加图象的形式,该图象在ViewPort中心并且不被缩放。这可以用于在按钮的中央放置一个形状等等。这“第十个栅格”称为点符(glyph),并且由GlyphImageSource揭示:
 public sealed class System.Windows.Media.NineGrridBrush:Brush
 {
  public NineGridBrush(ImageSouree imageSource,
              int LeftBorder,
              int RightBorder,
              int TopBorder,
              int BottomBorder;
public NineGridBrush(ImageSource imageSource,
            int LeftBorder,
            int RightBorder,
            int TopBorder,
            int BottomBorder,
            ImageSource glyphImage);
 public new NineGridBrush Copy();//hides Brush.Copy()
//Default is null
 public ImageSource ImageSource{get;set;}
 //Default is 0
public new NineGridBrush Copy();//隐藏Brush.Copy()
 //默认为null
 public ImageSource ImageSource{get;set;}
 //默认为0
 public int LeftBorder{get;set;}
 //默认为0
 public int RightBorder{get;set;}
 //默认为0
 public int TopBorder{get;set;}
 //默认为0
 public int BottomBorder{get;set;}
 //默认为null
 public ImageSource GlyImageSource{get;set;}
}
注意边成员以图象像素从图象边缘起计数。
NineGridBrush的用于标记的简单句法:
nine-grid-brush:
 ″NineGrid″image-uri int int int int[glyph-image-uri]
四个整数分别是LeftBorder,RightBorder,TopBorder和BottomBorder的值。用于第十个栅格或点符的最后的URI,是可选的。
Pen是用Brush和描述如何笔划空间/几何图形的的其它参数的对象。概念上,Pen描述如何从Geometry创建笔划区域。创建一个新区域,它基于几何图形的边、Pen的Thickness、PenLineJoin、PenLineCap等。一旦创建了这个区域,就用Brush填充它。
    public sealed class System.Windows.Media.Pen:Changeable
    {//构造函数
     Public Pen();
     public Pen(Brush brush,double thickness);
     public new Pen Copy();//隐藏Changeable.Copy()
     //属性
     //默认为DashArrays.Solid(非虚线)
     public DoubleCollection DashArray{get;set;}
     //默认为0
     [Animations(DashOffsetAnimations)]
     public double DashOffset{get;set;}
     public DoubleAnimationCollection DashOffsetAnimations
{get;set;}
     //默认为Flat
     public PenLineCap StartLineCap{get;set;}
     //默认为Flat
     public PenLineCap EndLineCap{get;set;}
     //默认为Flat
     public PenDashCap DashCap{get;set;}
     //默认为Miter
     public PenLineJoin LineJoin{get;set;}
     //默认为10
     public double MiterLimit{get;set;}
     //默认为null
     public Brush Brush{get;set;}
     //默认为1.0
     [Animations(ThicknessAnimations)]
     public double Thickness{get;set;}
     public Double AnimationCollection ThicknessAnimations
{get;set;}
    }
    PenLineCap确定如何绘制所笔划的直线的末端:
    public enum System.Windows.Media.PenLineCap
    {
     //这实际上没有线帽--使直线在线的最后一点处为方形
     Flat,
     //由直径等于线宽的半圆作为线帽
     Round,
     //由三角形作为虚线帽
     Triangle,
     //由边长等于线宽、以末端点为中心的正方形作为线帽
     Square
}
PenDashCap确定如何在虚线笔划的直线中绘制每段长划的末端:
public enum System.Windows.Media.PenDashCap
{
 //这实际上无虚线帽--使直线在线的最后一点为方形
 Flat,
 //由直径等于线宽的半圆作为虚线帽
 Round,
 //由三角形作为虚线帽
 Triangle
}
PenLineJoin确定当笔划直线时如何连接:
 public enum System.Windows.Media.PenLineJoin
{
  //在相交的线段的外部边缘的交叉点上创建尖角
  Miter.
  //类似于Miter,但是角是圆的
  Round,
  //beveled联合,这产生对角的角
  Bevel
  }
DashArrays类包括静态属性,它提供对公用的、公知的虚线风格的访问:
 public sealed System.Windows.Media.DashArrays
{
 //实虚线阵列(无虚线)
 public static DoubleCollection Solid{get;}
 //Dash--3长1短
 public static DoubleCollection Dash{get;}
 //Dot--1长1短
 public static DoubleCollection Dot{get;}
 //DashDot--3长1短,1长1短
 public static DoubleCollection DashDot{get;}
 //DashDotDot--3长1短,1长1短,1长1短
 public static DoubleCollection DashDotDot{get;}
}
颜色
颜色体系结构是在一些一般原则上建立的,包括颜色要求上下文;因此颜色值将具有显式赋值的上下文或者隐含地假定默认为最小化工作流中的颜色失配。而且,核心平台设计要求最小的代码路径和具有长寿命跨越安全、可靠性、可维护性、进一步的扩展和性能的API;因此呈现核心可主要限制于scRGB代码路径,进入的内容流将被转换到该路径,而出去的流将从该路径转换得到(也允许具有较低质量的附加的sRGB传统路径)。注意,“scRGB”指内部向量图形默认表示,基于IEC 61966-2-2国际标准;(尽管还没有提供“sc”的含义的官方定义,这里使用“标准合成(standing compositing)”来帮助阐明这是用于合成处理的优化空间)。
性能要求尽可能接近颜色对象定义/描述阶段执行复杂处理,而不是在实时呈现阶段;这要求(本质上立即)基于规范将对API的颜色参数转换成scRGB,并且要求为非-scRGB定义的对象保存和同步scRGB颜色值。易于使用要求分层化的API,其中首先揭示最普通的开发者情形,而最高级的情形具有清楚但最小的API;因此提供sRGB API(但在内部立即被转换成scRGB),提供scRGB,并且提供最小上下文相关的API以支持高级的CMYK(青-深红-黄-黑)、单色、人类视觉系统和多信道解决方案。由于scRGB本质上是“无限”的色域,因此要求附加的设备特征和色域映射解决方案以用真实世界设备“钩住”scRGB工作流。
颜色是心理感觉,通常是由外部物理感觉引起。这意味着,基于计算机的颜色要求物理上下文以便有效地通过设备并在用户之间传送可感知的颜色。历史上的各种技术曾经不一致地提供颜色体系结构实现的合理的上下文意义,例如,这导致“红色”意味着一个设备或用户的“橙色”,或者另一个的“粉红色”,而几乎没有可行方法来解决这种失配。
本体系结构提供任何颜色对象的隐含(使用默认)和显示式颜色上下文的组合。这意味着将不存在没有上下文意义的颜色对象。这是不完善的技术,并且因而该体系结构的一个方面是要以可以随着技术进步发展的方式提供一致的颜色上下文。注意,大多数计算机用户(和大多数开发者)不想处理颜色管理,而更喜欢颜色仅应当正确地工作。
一般而言,该体系结构试图最小化内部代码路径来达到这样的程度,即通过在内部支持两个基本代码路径,一个用于质量和未来的硬件,而另一个用于传统和存储器/性能约束。MIL核心内部呈现和合成引擎支持32bpp sRGB和128bpp浮点型scRGB(尽管64bpp scRGB也在考虑之中,并且有些64bpp实例支持最好用定点型实现,有些用浮点型而有些用整数)。
该体系结构提供从捕捉到显示到编辑到存储到打印的128bpp scRGB路径(显示是128bpp后缓冲器和10bpc或更大的前缓冲器),并且允许传统的32bppsRGB,它牺牲性能、存储器和/或带宽的质量。
本发明的颜色管理通过为设备和应用提供额外的灵活性来改进原先的缺点并提供基于简档的颜色管理解决方案。最普通的情景基于scRGB和sRGB颜色对象以支持取得和设置普通UI元素的颜色值,并且支持网络、多媒体和计算机图形的大多数内容创建。不太普通的情景包括使用具有用于专业摄影工作流的特定工作空间简档的RGB颜色上下文,使用CMYK颜色值以编辑用于预印刷(prepress)和图形设计工作的颜色对象、单色与多信道颜色工作流(支持适当位置(niche)打印和印刷情景以及提供灵活性以支持还没有定义的未来的工作流)。HVSV(基于人类视觉系统的空间)工作流支持某些适当位置专业摄影编辑情景。
为符合继续在质量和位深度方面进步的捕捉传感器技术,成像将支持至少64bpp格式用于每一特征/API,以便支持当代数字否定主动性。当本发明实现向量图形的新体系结构时,向量图形将以每信道32位浮点型精度实现。这个实现实际上被“隐藏”,以便提供传统的8bpc颜色访问以及灰度和HSV接口。
另一类型的颜色数据称为颜色数据,诸如“CornflowerBlue”或“Pantone”颜色。通过提供基于扩展的传统颜色管理简档的颜色上下文,提供非常通用和强大的颜色命名界面。为保持与先前API和普通实践的某些传统兼容性,将朝着sRGB输入偏置默认的构造函数。
支持向量图形的颜色空间被划分成本地scRGB支持、sRGB和不要求显式颜色上下文的相似空间的属性支持、与sRGB或scRGB紧密相关的、也不要求显式相关的颜色上下文的颜色空间诸如HSV(色调、饱和度和值)的方法支持、命名的颜色和有关的颜色空间诸如调色板和基于或者隐含地或者显式地相关的颜色上下文的索引的颜色空间、和要求附加的颜色信道以及显式相关的颜色上下文的颜色空间诸如CMYK、高保真颜色(CMYK加上橙色和绿色)、CcMmYK喷墨颜色空间和潜在地将来的光谱颜色支持。
尽管这些颜色空间被转换成scRGB或sRGB用于在MIL核心或合成引擎中分离,但它们可以使用向量图形标记语言如程序设计语言来存储或送到打印机(诸如CMYK)。颜色标记句法包括四个基本描述机制:十六进制,已知颜色,sRGB属性和高级颜色上下文。前三个假定sRGB颜色空间颜色上下文。
下面的例子使用这四个机制来创建渐变:
Example:
<Canvas Width=″100px″Height=″100px″
 Background=″VerticalGradient#ee7711 ComFlowerBlue″
 xmlns=″using:System.Windows;System.Windows.Controls;System.Windows.Docum
 ents;System.Windows.Shapes;System.Windows.Media;System.Windows.Presenters″
 >
   <Rectangle Top=″12.5%″Left=″0″Width=″100%″Height=″12.5%″>
     <Rectangle.Fill>
      <RadialGradient>
        <GradientStop Offset=″0″ Color=″sGray.icc 0.5″/>
          <GradientStop Offset=″0.5″>
            <GradientStop.Color>
             <Color A=″0.8″R=″0.2″G=″1″B=″0.2″/>
            </GradientStop.Color>
           </GradientStop>
          <GradientStop Offset=″1″Color=″mswopintent8.icm 0.9 0.2 0.1 0.3″/>
         </RadialGradient>
        </Rectangle.Fill>
       </Rectangle>
      </Canvas>
第一个背景颜色指定为十六进制(#ee7711)。这个十六进制表示与.NET框架V1和WinForms如何指定颜色相同。它灵活地允许四种不同的变体:#RGB,#ARGB,#RRGBBB,或#AARRGGBB。
第二背景颜色指定为已知的颜色(CornFlowerBlue)。这个表示与.NET框架V1和WinForms如何指定颜色相同。它基于命名的颜色值。命令的颜色解决方案将支持Pantone、Trumatch或其它要用颜色上下文支持的命令颜色。这也将支持alpha信道设置。
第一个渐变停止符是使用颜色上下文(“sGray.icc 0.5”)来指定的。该文本串指定颜色上下文文件名,它可以是URL或URI。这个例子是例示对单色打印的清楚支持而不要求在打印呈现时将RGB值首先被翻译成单色值。
第二个渐变停止符是使用sRGB属性(A=″0.8″R=″0.2″G=″1″B=″0.2″)来指定的。这个表示与.NET框架V1和WinForms如何指定颜色相同。
第三个渐变停止符使用颜色上下文(=″mswopintent8.icm 0.9 0.2 0.10.3″)。该文本串指定颜色上下文文件名,它可以是URL或URI并且可支持alpha信道设置。这个样本示出CMYK支持,诸如Publisher或其它这样的应用所要求的。
合在一起,这些例子提供非常健全和清楚的句法以支持颜色要求。注意,颜色上下文可全局地指定并且要求内部颜色引用来符合这个全局上下文例如用于性能优化。
如上所述,要求颜色上下文用于颜色对象,无论它们是基于向量还是基于光栅。在粗略的层次上,可以认为颜色上下文是简档,提供颜色对象的颜色空间与人类视觉系统之间的关系。颜色上下文提供关于用户颜色空间与scRGB颜色空间(或人类视觉系统颜色)之间的关系的信息。这允许以有效方式“来回(round-tripping)”于CMYK和先前一直不可行的其它颜色信息之间。
实际上现在,字面上存在数百个不同的颜色空间,诸如sRGB,scRGB,AdobeRGB,BruceRGB,AppleRGB,TomRGB,CorbisRGB,JoeRGB,HSV,HSB,XYZ,LAB,LUV,YUV,YCC,CMYK,CcMmYK,CMYKOG,浅淡灰度,亮度灰度和许多许多其它的。这些独立颜色空间的许多可以分解成颜色空间类诸如主要由包含近似于对具有包括伽马、原色、白点和位精度的定义语义的红色、绿色和蓝色的视觉感觉的三个信道定义的RGB空间。位精度是必要的,因为较低的位精度(诸如每信道8位)一般要求扩展、非线性补偿以实现合理的编码效率。
提供颜色上下文类将可能的颜色空间类的集合减少到一个小得多的集合,诸如灰度、RGB、HSV、CMYK、LAB、LCH、CcMmYK、CMYKOG、光谱颜色和特殊的效果空间诸如双色、三色和四色空间用于艺术效果。通过组合共享同一基础意义但提供不同坐标系统(与直线和极几何图形相似)的空间,进一步的减少是可能的。这将使HSV为RGB颜色空间类之上的一个方法,并使LCH为LAB颜色空间类之上的一个方法。
也有可能将特殊效果颜色空间与光谱颜色组合,以及包括对CcMmYK和CMYKOG的支持,并且具有仅在作为一个动态阵列的这个上下文中的颜色值因为只有高级用户将使用这个特征。进一步的减少有可能将颜色空间减少到支持sRGB和其它RGB空间的scRGB和具有颜色上下文的多信道颜色空间。这留下合理数量的基本颜色空间类要支持,仅包括scRGB和多信道空间。
将ColorContext或者与向量图形Color类相关联,或者与ImageData对象相关联。另一个选择是限制Visual到单一ColorContext。这将帮助优化在许多环境中颜色转换和确认的数量,并且可以对于应用开发者更自然,例如,个别控件不可能使用来自多个颜色系统的颜色。注意,仍允许为通过允许动态改变显式地使用多个颜色类型的高级应用改变颜色简档。ColorContext还允许指定在两个设备色域之间的呈现意图或色域映射并且与颜色对象相关联。由于ColorContext只处理单一颜色对象,因此目的地色域可以是虚拟设备。这允许ColorContext既包含颜色空间的目标描述又包含颜色的主观呈现意图。
颜色名称是嵌入在简档中的简单的查找表,简档与提供在基于ColorContext类型的颜色值与实际颜色名称之间的链接的颜色上下文相关联。这允许不同的颜色命名词典用于每个颜色对象。例如,有可能将一种类型的命名系统诸如具有过程颜色对象的Trumatch与另一类型的命名系统诸如具有点颜色对象的Pantone相关联。
公有的向量图形Color类型当将数据传输给较低层系统时通过最小化转换来符合较低层系统以优化性能。将独立的“本地的”(即CMYK或这类)浮点数值集合存储在颜色上下文中并且在任何改变发生时同步它。本地的ColorContext colorValue是基于浮点数阵列的值类型(结构),以便透明地支持灰度、RGB和甚至CMYK颜色空间。本地的ColorContext ColorValue阵列应当是动态的并且不限于1、3、4或甚至8个颜色信道。这允许具有这同一体系结构的光谱或删减的光谱颜色过程解决方案。注意,尽管相对有时只是部分使用的五-元素阵列的成本,分配的成本相当大,但这确保一致的、连贯的和灵活的解决方案用于将来,并且在使用scRGB工作流时没有成本为零。Alpha值与ColorContext ColorValue分开,因为它是不同的概念并且在大多数使用中被不同地对待。
名称 类型 描述 其它信息
InternalColor  Float Red,FloatGreen,FloatBlue,Float Alpha 与内部呈现颜色结构相同的结构以优化性能 内部结构,这第二个内部结构用于支持数据的有效排列。
context  ColorContext 颜色上下文,提供与使用颜色上下文信息有关的方法 携带与InternalColor值同步的本地颜色值
名称 变元 描述 其它信息
FromProfile(...) String 基于ICC或其它简档文件名的构造函数 公有静态
FromProfileAndRenderingIntent(...) String,String 基于ICC或其它简档文件名的构造函数 公有静态
FromAValues(...) Float,float[],文件名 基于alpha信道值、浮点值和ICC或其它简档文件名的一般构造函数 公有静态
FromValues(...) Float[],文件名 与FromAValues(...)相同但alpha假定为1.0f 公有静态
FromARGB(...) byte,byte,byte,byte 基于alpha、红色、绿色和蓝色的sRGB值的传统sRGB构造函数 公有静态,sRGB值在内部被转换成用于处理的scRGB
FromRGB(...) byte,byte,byte 基于红色、绿色和蓝色sRGB值(alpha假定为1.0f)的传统sRGB构造函数 公有静态,sRGB值在内部被转换成scRGB用于处理
FromScRGB(...) Float,float,float,float 基于alpha、红色、绿色和蓝色scRGB值的scRGB构造函数 公有静态
注意,获得系统颜色UI对象的颜色值可以独立于其它上下文,主题(theming)的其它更高级类型也是如此,并且应当用具有应用模型/主题API的其它系统度量标准来收集。
 名称  返回类型 描述 其它信息
 R  byte 当前颜色的红色scRGB分量的红色sRGB值 R/W
 G  byte 当前颜色的红色scRGB分量的绿色sRGB值 R/W
 B  byte 当前颜色的红色scRGB分量的蓝色sRGB值 R/W
 A  byte 当前颜色的红色scRGB分量的alpha sRGB值 R/W
 ScR  float 当前颜色的红色scRGB分量的红色scRGB值 R/W
 ScG  float 当前颜色的红色scRGB分量的绿色scRGB值 R/W
 ScB  float 当前颜色的红色scRGB分量的蓝色scRGB值 R/W
 ScA  float 当前颜色的红色scRGB分量的alpha scRGB值 R/W
注意,scRGB值可以在小于0.0和大于1.0的范围内以支持扩展的动态范围和色域。
Color对象的运算符覆盖是上下文特定的,因为混合和添加颜色是颜色空间依赖的。例如,亮度RGB空间是加法的和线性的,因此典型的数学运算是全然直觉的,但浅淡RGB空间和CMYK空间既不是线性的也不是加法的,由此这操作导致不同的视觉效果。另外,大多数Color运算可以导致在所想要的色域之外的值并且因而要求色域映射补偿。这可以与低质量箝位一样简单或者可以明显更复杂。
动画运算符重载如果专门限制于scRGB ColorContext则可以提供某些运算符重载,因为scRGB基于物理光并且线性和加法性地混合。CMYK、sRGB和其它颜色空间具有很不同的混合模型。
名称  返回类型  变元 描述 其它信息
+  Color  Color,Color 依赖上下文的颜色加法 RGB上下文是线性的wrt亮度(光子如何混合),它对于scRGB和计算机图形是正确的
Add  Color  Color,Color 依赖上下文的颜色加法 公有
-  Color  Color,Color 依赖上下文的颜色减法 公有
Subtract  Color  Color,Color 依赖上下文的颜色减法 公有
*  Color  Color,Color 依赖上下文将颜色乘以浮点值 公有
Multiply  Color  Color,Color 依赖上下文将颜色乘以浮点值 公有
Equals  Bool  Color,Color 如果颜色对象等于当前颜色则返回true 公有
 Equals  Bool  Object 如果两个颜色值相等则返回true 公有
 ==  Bool  Color,color 如果两个颜色值相等则返回true 公有
 IsEqual  Bool  Color,color 如果两个颜色值相等则返回true 公有
 !=  Bool  Color,color 如果两个颜色值不相等则返回true 公有
 IsNotEqual  Bool  Color,color 如果两个颜色值不相等则返回true 公有
如在多信道颜色中使用的相似方法也可以用于支持HSB、YCC和YUV和相似的与sRGB或scRGB紧密相关的颜色空间。
名称  返回类型  变元 描述 其它信息
Clamp  Color  Void 将颜色值箝制在[0.0...1.0] 公有
GetHashCode  int  Void 返回Color散列码 公有
Name  String  返回颜色名称 颜色上下文调用的冗余
ToRgbColor  无  Color 返回当前颜色的scRGB等价颜色 公有
ToString  String  Void 返回颜色的格式化串值 公有
AreClose  Bool  Color,Color 如果使用FloatUtil函数 静态
颜色值接近则返回true
IsClose  Bool  Color 如果使用FloatUtil函数颜色接近于当前颜色则返回true 公有
SetRedneringIntent  Bool  String 如果ColorContext的呈现意图成功则返回true 公有
在基于sRGB的rgb和argb形式中的浮点值在从0.0到1.0的尺度上指定。按照定义,这些值将从不在这个范围之外并且因此应当被箝制。相反,基于scRGB的值是在0.0之下和1.0之上也是有效的。这些值应当只在目的地设备不能支持扩展的色域时才被剪辑。这可以通过查询与目的地色域相关联的简档来确定。理想地,对于显示,图形硬件可以使用DX的色域管理功能来关心这个问题。
如果正在分析的串是无效的,则颜色将被初始化为ARGB=(0.0,0.0,0.0,0.0)。
当持续时,如果颜色被创建为已知的颜色,则将值写成已知的颜色名称。如果否,则如果alpha为1.0将使用rgb(float,float,float)形式。如果alpha不是1.0则将使用argb(float,float,float,float)形式。
光栅图形或者成像或者像素格式与上面的向量图形解决方案不同。简单地说,成像输入可以是从1bpp直至128bpp的几乎一切,具有从黑色和白色到sRGB到scRGB到CMYK的各种各样支持的颜色空间。因此,ImageData的颜色解决方案要求ImageData或像素格式的ColorContext。这可以从标准文件格式内嵌入的简档或嵌入的伽玛和色度信息来产生。这消除了在ImageData类中提供伽玛或其它冗余属性或字段的需求。
MILRender代码理解32-bpc颜色规范(scRGB)。输入颜色转换应当在呈现代码之上发生(但不必在不受管理的代码之外)。
颜色值的动画应当主要发生在线性空间内。它可以是线性化的HSV空间或者scRGB,但对于“弹跳(bounce)”和其它每信道动画是要线性的以有意义。
描述三个颜色保真度模式,包括:
完全--32bpc通过系统;128bpp后-缓冲器/10-bpc+前-缓冲器;完全32bpc合成。
混合--32bpc颜色规范/内插;高频振动或箝制颜色到32bpp预-合成。
传统--32bpc颜色规范--立即被转换成32bpp;32bpp合成/输出。
这些模式将由两个后缓冲器格式来支持,即128-bpp 1.0伽玛(scRGB)和32-bpp2.2伽玛(sRGB)。也为处理较低-位-深度(16和8bpp显示)前-缓冲器情景提供支持。在显示时高频振动后-缓冲器以防止在合成中的损耗。
对象的Geometry类可以用于用Pen和Brush来剪辑、击中测试和呈现基于2D向量的数据。所派生的Geometry类提供更专用的建立和枚举语义。提供许多形状-专用Geometry类型,以及通用化的PathGeometry,允许显式地定义更复杂形状的Geometry。对于那些熟悉GDI+的人,最熟悉的是GraphicsPath。
教科书 GDI+ 本发明
 Path  GraphicsPath  PathGeometry
 SubPath  GraphicsPath  PathFigure
Geometry是抽象基类。
[TypeConverter(typeof(PathGeometryConverter))]]
public abstract class Geometry:Animatable,IDisposable
{
 internal Geometry();
 public new Geometry Copy();
 //如果动画,Bounds返回“当前”限制范围
 //这不考虑任何笔
 public virtual Rect Bounds{get;}
 //这考虑笔。当显示动画时,这取几何图形和笔两者的“当前”值。
 public virtual Rect GetBounds(Pen pen);
 //如果没有变换返回本身。
 public Transform Transform{get;set;}
//释放由Geometry(镶嵌,路径数据,等等)高速缓存的资源
 public virtual void Dispose();
}
为设置应用于几何图形的变换,设置Transform属性。
GeometryCollection是多个Geometry对象的集合,这些对象已经使用在它们定义的区域上特定的布尔操作组合起来。这个对象允许比有可能严格地使用PathGeometry内的PathFigure对象更容易地建立Geometry对象的视件组合。
组合模式枚举指示集合内几何图形区域的组合。布尔操作Union、XOR、Intersect是可交换的并且因此顺序无关地应用于几何图形。Complement和Exclude是不交换的并因此在第一几何图形与各个剩余的几何图形之间定义。换言之,{g1,g2,g3}的exclude组合将应用为((g1 exclude g2)and(g1exclude g3))。Complement指定,现有区域由从新区域中移除现有区域的结果来代替。换言之,从新区域中排除现有区域。Exclude指定,现有区域由从现有区域中移除新区域的结果来代替。换言之,从现有区域中排除新区域。Intersect指通过取区域的交来组合区域,Union指通过取两个区域的并来组合区域,而Xor指通过取由一个区域或另一个区域包围但不是两者都包围的区域来组合区域:
public enum System.Windows.CombineMode
{
 Complement,
 Exclude,
 Intersect,
 Union,
 Xor
}
    public enum System.Windows.CombineMode
    {
      Complement,
      Exclude,
      Intersect,
      Union,
      Xor
    }
    public sealed class GeometryCollection:Geometry,IAddChild,IList
    {
      public GeometryCollection();
      public GeometryCollection(int capacity);
      public GeometryCollection(
       GombineMode combineMode,
       papamsGeometry[]collection);
     public GeometryCollection(
       CombineMode combineMode,
       ICollection collection);
     public GeometryCollection(
       CombmeMode combineMode,
       ICollection collection,
       Transform transform);
public new GeometryCollection Copy();
//指定如何组合几何图形
 [DefaultValue(CombineMode.Union)]
 public CombineMode CombmeMode{get;set;}
 //IEnumerable
  public IEnumerator GetEnumerator();
 //ICollection
 public int Count{get;}
 public bool IsSynchronized{get;}
 public object SyncRoot();
 public void CopyIo(Array array,int index;
 //IList
 public bool IsFixedSize{get;}
 bool IList.IsReadOnly{get;}
 object IList.this[int index]{get;set;}
 int IList.Add(object value);
 public void Clear();
 bool IList.Contains(object value);
 int IList.INdex Of(object item);
 void IList.Insert(int index,object value);
 void IList.Remove(object value);
 public void RemoveAt(int index);
 //附加的函数
public int Capacity{get;set}
public Geometry this[int index]{get;set;}
public int Add(Geometry geometry);
public bool Contains(Geometry geometry);
public int IndexOf(Geometry geometry);
public int IndexOf(Geometry geometry,int startIndex;
public int IndexOf(Geometry geometry,int startIndex,int count);
public int LastIndexOf(Geometry geometry);
public int LastIndexOf(Geometry geometry,int startIndex);
public int LastIndexOf(Geometry geometry,int startIndex,int count);
public void Insert(int index,Geometry geometry);
public void Remove(Geometry geometry);
public void AddRange(GeometryCollection geometryCollection);
public void SetTange(int index,GeometryCollection geometryCollection);
publicvoid InsertRange(int index,GeometryCollection geometryCollection);
 public void RemoveRange(intindex,int count);
 publlc GeometryCollection GetRauge(int index,int count);
 public Geometry GetOptimizedGeometry();
}
 GetOptimizedGeometry()在可能的地方折叠几何图形的集合,结果不必是GeometryCollection。这可能包括优化诸如将毗邻的矩形几何图形组合成单个矩形几何图形,执行毗邻路径几何图形之间的布尔操作以创建新的路径几何图形,或者用同一组合模式使GeometryCollection变平。在许多不同的上下文中使用几何图形的情况下,这提供在处理和存储方面的性能改进。
下面的例子演示使用GeometryCollection的标记:
<Path Fill=”Red″>
 <Path.Data>
  <GeometryCollection Tmnsform=″translate(42525)″CombineMode=″Xor″>
   <RectangleGeometry Rect=″00100100″/>
   <RectangleGeometry Rect=″5050100100″/>
  </GeometryCollection>
 </Path.Data>
</Path>
PathGeometry是PathFigure对象的集合。每个PathFigure对象是由一个或多个实际定义其形状的PathSegment对象组成。通过取所包含的区域(具有其Filled属性设置为true的PathFigure并应用FillRule以确定所包围的区域)来定义PathGeometry的被填充区域。图13代表PathGeometry对象关系。
FillRule枚举项指定如何将Geometry内包含的Figure对象的相交区域组合起来以形成该Geometry的结果区域:
public enum System.Windows.Media.FillRule
{
 EvenOdd,
 NonZero,
}
{
 public PathGeometry();
 public PathGeometry(params PathFigure[]figures);
 public PathGeometry(ICollection figureCollection);
 public PathGeometry(
  ICollection figureCollection,
  FillRule FillRule,
  Transform transform);
 public new PathGeometry Copy();
 [DefaultValue(FillRule.EvenOdd)]
 public FillRule FillRule{get;set;}
 //这个方法将来自特定Geometry的Figure添加到这个PathGeometry,
 //但将使用当前的FillRule代替该几何图形的FillRule。
 public void AddGeometry(Geometry geometry);
 public void AddFigure(Pathfigure figure);
 public void AddPointAndType(
  Point[]points,
  byte[]types);
 public PathFigureCollection Figures{get;set;}
 public PathGeometry GetWidenPathGeometry(Pen pen);
 public PathGeometry GetOutlinedPathGeometry();
}
EvenOdd规则确定在画布上的点的“内部性(insideness)”,通过从该点到无穷远以任何方向绘制一条射线并且随后检查形状的线段与射线交叉的位置。从零的计数开始,每次Segment从左至右与射线交叉时加一而每次路径线段从右至左与射线交叉时减一。在计数交叉之后,如果结果是零则该点在该路径之外。否则,它在内部。
NonZero规则确定在画布上的点的“内部性”,通过以任何方向从该点到无穷远绘制一条射线并计数来自射线交叉的给定形状的路径Segment的数量。如果这个数量是奇数,则该点在内部;如果是偶数,则该点在外部。
为将其它几何图形类型转换成路径几何图形Figure用于包含其它外形,使用AddGeometry方法。这添加在几何上匹配输入几何图形的外形。对于非-动画的几何图形,匹配是精确的,而动画的几何图形在转换中可能有损耗。有损耗转换的原因是输入几何图形的动画参数不匹配适合线段的形式。
 几何图形 无损耗/有损耗 外形
 LineGeometry 有损耗w/动画 StartSegment和LineSegment
 RectangleGeometry 有损耗w/动画 PolySegment
 EllipseGeometry 有损耗w/动画 ArcSegment和ArcSegment
 GeometryCollection 有损耗w/动画 许多种类的线段。
 PathGeometry 有损耗w/动画 除Arc和Quadratic线段之外的全部。
不保证所得到的PathGeometry的枚举和结构精确匹配输入几何图形。
外形集合,是PathFigure对象和定义PathGeometry的基本内容的集合:
public sealed class PatbFigureColleetion:Animatable,IAddChild,IList
{
  public PathFigureCollection();
  public PathFigureCollection(int capacity);
  public PathFigureCollection(params PathFigure[] figures);
  public PathFigureCollection(ICollection figureCollection);
  public new PathFigureCollection Copy();
  //IEnumerable
  public IEnumerator GetEnumerator();
  //ICollection
  public int Count{get;}
  public bool IsSynchronized{get;}
  public object SyncRoot();
  public void CopyTo(Array array,int index);
 //IList
 public bool IsFixedSize{get;}
 bool IList.IsReadOnly{get;}
 object IList.this[int index]{get;set;}
 int IList.Add(object value);
 public void Clear();
 bool IList.Contains(object value);
 int IList.IndexOf(object item);
 void IList.Insert(int index,object value);
  void IList.Remove(object value);
  public void RemoveAt(int index);
//附加的函数
  public int Capacity{get;set;}
  public PathFigure this[int index]{get;set;}
  public int Add(PathFigure figure);
  public bool Contains(PathFigure figure);
  public int IndexOf(PathFigure figure);
  public int IndexOf(PathFigure figure,int startIndex);
  public int IndexOf(PathFigure figure,int startIndex,int count);
  public int LastIndexOf(PathFigure figure);
  public int LastIndexOf(PathFigure figure,int startIndex);
  public int LastIndexOf(PathFigure figure,int startIndex,int count);
  public void Insert(int index,PathFigure figure);
  public void Remove(PathFigure figure);
  public void AddRange(PathFigureCollection figureCollection);
  public void SetRange(int index,PathFigureCollection figureCollection);
  public void InsertRange(int index,PathFigureCollection figureCollection);
  public void RemoveRange(int index,int count);
  public PathFigureCollection GetRauge(int index,int count);
}
PathFigure是定义线段集合的Geometry的子-部分。这个线段集合是一系列单连接的两-维的PathSegment对象。PathFigure可以是具有确定面积的封闭形状,或者定义曲线但没有包围的面积的一系列连接的Segment。PathFigure类包括许多有用函数,允许简化更简单地从显式的ArcTo/LineTo/(和其它)方法调用来构造PathFigure而不要求PathSegment对象。显式的AddSegment调用可以用于添加合成的Segment。
public sealed class PathFigure:Animatable
{
 public PathFigure();
 public PathFigure(params PathSegment[]segments;);
 public PathFigure(ICollection segmentCollection);
 public PathFigure(ICollection segmentCollection,bool isFilled);
 public new PathFigure Copy();
 [DefaultValue(true)]
 public boll isFilled{get;set;}
 //在初始点开始外形。
 public void StartAt(Point pt);
 public void StartAt(Point pt,PointAnimationCollectionptAnimations);
 //从当前点到指定的新点添加线段。将当前点更新到新位置。
 public void LineTo(Point pt);
 public void LineTo(Point pt,PointAnimationCollection
     ptAnimations);
 //添加在当前点开始然后到点阵列中各个点的折线。
 //将当前点更新到阵列的最后一个点。
 public void PoiyLineTo(Point[]points);
 public void ArcTo(
  Point pt,
  Size  sz,
 double xRotation,
 bool largeArcFlag,
 bool sweepFlag);
public void ArcTo(
 Point pt,
 PointAniamtorCol lection ptAnimations,
 Size sz,
 SizeAnimationCollection szAnimations,
 double xRotation,
 DoubleAnimationCollection xRotationAnimations,
 bool largeArcFlag,
 bool sweepFlag);
//使用当前点作为第一控制点添加三次贝塞尔线段。
//将当前点更新到目的地点。
public void BezierTo(
 Point pt1,
 Point pt2,
 Point ptDest);
public void BezierTo(
 Point pt1,
 PointAnimatonCollection pt1Animation,
 Point pt2,
 PointAnimatonCollection pt2Animation,
 Point ptDest
 PointAnimatonCollection ptDestAnimation);
 //使用当前点作为第一控制点然后一次通过3个点重复来添加三次贝塞尔曲线部分。
 //将当前点更新阵列的最一个点。
//当传入的点数量不是3的倍数时,抛出无效变元异常。
public void PolyBezierTo(Point[]points);
//使用当前点作为第一控制点添加二次贝塞尔曲线部分。
//将当前点更新到目的地点。
public void QuadraticBezierTo(Point pt1,Point ptDest);
public void QuadraticBezierTo(
 Point pt1,
 PointAnimationCollection ptlAnimation,
 Point ptDest,
 PointAnimationCollection ptDestAnimation);
//使用当前点作为第一控制点然后一次通过2个点重复来添加二次贝塞尔曲线部分。
 //将当前点更新阵列的最一个点。
 //当传入的点数量不是2的倍数时,抛出无效变元异常。
 public void PolyQuadraticBezierTo(Point[]points);
 //关闭外形。不可以添加新的线段。
 public void CloseFigure();
 //笔划新外形的线段。默认为true。
 public void StrokeNewSegments(bool strokeNewSegments);
 //添加新Segment到PathFigure
 public void AddSegment(PathSegment segment);
 public PathSegmentCollection Segments{get;set;}
 public PathFigure GetFlattenedPathFigure(float flatness);
}
外形要求一个起始点,因为每个线段保持相对于添加的最后一个点的连续性。为指定起始点,调用StartAt(pt)或Add(new StartSegment(pt))。在添加线段之后,为添加将最后一个点连接回起点的适当地封闭的线段,使用CloseFigure()或Add(new CloseSegment())。起始和封闭线段出现在线段集合中。
如果建立PathFigure并且StartSegment不是集合中的第一个线段或者CloseSegment(如果存在)不是集合中的最后一个线段,则抛出异常。StartSegment和CloseSegment在外形中的任何其它位置中不是有效的,异常是完全空的线段集合。
PathFigure.IsFilled属性显式地控制是否要使用封闭的外形所包含的区域用于击中测试、呈现和剪辑。如果这个属性设置为false,则将只使用PathFigure的轮廓,并且它所包含区域将不贡献给PathGeometry的整个区域。这个属性的默认值是true。
为枚举PathFigure的内容为点,一个直接了当的方法是使外形变平并且检查所得到的PathSegmentCollection。相对于动画和曲线线段参数,变平过程是有损耗的,然而通过PolyLineSegment揭示未加工的点数据用于进一步的点处理。
PathSegmentCollection是PathSegment对象和定义PathFigure的基本内容的集合:
public sealed class PathSegmentCollection:Animatable,IAddChild,IList
{
  public PathSegmentCollection();
  public PathSegmentCollection(int capacity);
  public PathSegmentCollection(params PathSegment[] segments);
  public PathSegmentCollection(ICollection segments);
  public new PathSegmentCollection Copy();
  //IEnumerable
  public IEnumerator GetEnumerator();
//ICollection
public int Count{get;}
public bool IsSyncbronized{get;}
public ibject SyncRoot();
public void CopyTo(Array array,int index);
//IList
public bool IsFixedSize{get;}
bool IList.IsReadOnly{get;}
object IList.this[int index]{get;set;}
int IList.Add(object value);
public void Clear();
bool IList.Contains(object value);
int IList.IndexOf(object item);
void IList.Insert(int index,object value);
void IList.Remove(object value);
public void RemoveAt(int index);
 //附加的函数
 public int Capacity{get;set;}
 public PathSegment this[int index]{get;set;}
 public int Add(PathSegment segment);
 public bool Contains(PathSegment segment);
 public int IndexOf(PathSegment segment);
 public int IndexOf(PathSegment segment,int startIndex);
 public int IndexOf(PathSegment segment,int starttudex,int count);
 public int LastIndexOf(PathSegment segment);
 public int LastIndexOf(PathSegment segment,int startIndex);
 public int LastIndexOf(PathSegment segment,int startIndex,int count);
 public void Insert(int index,PathSegment segment);
 public void Remove(PathSegment segment);
 public void AddRange(PathSegmentCollection segmentCollection);
 public void SetRange(int index,PathSegmentCollection segmentCollection);
 public void InsertRange(int index,PathSegmentCollection segmentCollection);
 public void RemoveRange(int index,int count);
 public PathSegmentCollection GetRauge(int index,int count);
PathSegment代表PathFigure的轮廓的一部分。简单的直线线段、椭圆-弧线段、三次贝塞尔曲线线段和二次贝塞尔曲线线段可以组合起来以形成PathFigure。
public abstract class PathSegment:Animatable
{
 internal PathSegment();
 public new PathSegment Copy();
 [DefaultValue(true)]
 public bool IsStroked{get;set;}
}
public sealed class StartSegment:PathSegment
{
 public StartSegment();
 public StartSegment(Point point);
 public StartSegment(Point point,PointAnimationCollection pointAnimations);
 public new StartSegment Copy();
 [Animations(“PointAnimations”)]
 public Point Point{get;set;}
 public PointAnimationCollection PointAnimations{get;set;}
}
public sealed class CloseSegment:PathSegment
{
 public CloseSegment(bool isStroked);
 public new CloseSegment Copy();
}
public sealed class LineSegment:PathSegment
{
 public LineSegment();
 public LineSegment(Point point,bool isStroked);
 public LineSegnent(
   Point point,
   PointAnimtionCollection pointAnimations,
   boolisStroked);
 public new LineSegment Copy();
 [Animations(“PointAnimations”)]
 public point Point{get;set;}
 public PointAnimationCollection PointAnimations{get;set;}
}
public sealed class BezierSegment:PathSegment
{
 public BezierSegment();
 public BezierSegment(
   Point point1,
   Point point2,
   Point point3,
   bool isStroked);
public BezierSegment(
  Point point1,PointAnimationCollection point1Animations,
   Point point2,PointAnimutionCollection point2Animations,
   Point point3,PointAnimationCollection point3Animations,
   bool isStroked);
 public new BezierSegment Copy();
 [Animations(“Point1 Animations”)]
 public Point Point1{get;set;}
 public PointAnimationCollection Point1Animations{get;set;}
 [Animations(“Point2Animations”)]
 public Point Point2{get;set;}
 public PointAnimationCollection Point2Animations{get;set;}
 [Animations(“Point3Animations”)]
 public Point Point3{get;set;}
 public PointAnimationCollection Point3Animations{get;set;}
}
public sealed class QuadraticBezierSegment:PathSegment
{
 public QuadraticBezierSegment();
 public QuadraticBezierSegment(
   Point point1,
   Point point2,
   bool isStroked);
public QuadraticBezierSegment(
  Point point1,PointAnimationCollection point1Animations,
  Point point2,PointAnimationCollection point2Animations,
  bool isStroked);
public new QuadratieBezierSegment Copy();
[Animations(“Pointl Animations”)]
 public Point Point1{get;set;}
 public PointAnimationCollection Point1Animations{get;set;}
 [Animations(“Point2Animations”)]
 public Point Point2{get;set;}
 public PointAnimationCollection Point2Animations{get;set;}
}
public sealed class PolyLineSegment:PathSegment
{
 public PolyLineSegment();
 public PolyLineSegment(Point[]points,bool isStroked);
 public PolyLineSegment(ICollection points,bool isStroked);
 public ntw PolyLineSegment Copy();
 public void AddPoint(Point point);
 public PointCollection Points{get;set;}
}
public sealed class PolyBezierSegment:PathSegment
{
 public PolyBezierSegment();
 public PolyBezierSegment(Point[]points,bool isStroked);
 public PolyBeziegment(ICollection points,bool isSteoked);
 putlicn new PolyBezierSegment Copy();
 public void AddPoint(Poiny point);
 public PointCollection Points{get;set;}
}
public sealed class PolyQuadraticBezierSegment:PathSegment
{
 public PolyQuadraticBezierSegment(Point[]polnts,bool isStroked);
 public PolyQuadraticBezierSegment(ICollection points,bool isStroked);
 public new PolyQuadraticBezierSegment Copy();
 public void AddPoint(Point point);
 public PointCollection Points{get;set;}
}
public sealed class ArcSegment:PathSegment
{
 public ArcSement();
 public ArcSegment(
   Point point,
   Size arcSize,
   double xRotation,
   bool largeArcFlag,
   bool sweepFlag,
   bool isStroked);
 public ArcSegment(
   Point point,
   PointAnimationCollection pointAnimations,
   Size arcSize,
   SizeAnimationCollection arcSizeAnimations,
   double xRotation,
   DoubleAnimationCollection xRotationAnimations,
   boollargeArcFlag,
   bool sweepFlag,
   bool isStroked);
pubic new ArcSe.ment Copy();
[Animations(“PointAnimations”)]
public Point Point{get;set;}
 public PointAnimationCollection PointAnimations{get;set;}
 [Animations(“SizeAnimations”)]
 public Size Size{get;set;}
 public SizeAnimationCollection SizeAnimations{get;set;}
 [Animations(“XRotationAnimations”)]
 public double XRotation{get;set;}
 public DoubleAnimatiouCollection XRotationAnimations{get;set;}
 public bool LargeArc{get;set;}
 public bool SweepFlag{get;set;}
}
每个添加到PathFigure的PathSegment对象还具有PathSegment.IsStroked属性。如果PathSegment具有设置为true的这个属性,则该特定的PathSegment将在用Pen呈现时贡献给PathGeometry的笔划区域。这还应用于击中测试和PathSegment的显式widen。当在PathFigure中的笔划和非笔划PathSegment部分之间切换时特定的行为是相同的,好象将Pen指定为虚线,因为将在PathSegment末端应用适当的虚线帽。
下面的例子演示使用PathGeometry、PathFigure和PathSegment的标记:
<Path Fill=″#4000FF00″Stroke=″Yellow″>
 <Path.Data>
  <PathGeometry Transform=″translate(22525)″FillRule=″EvenOdd″>
   <PathGeometry.Figures>
    <PathFigtureCollection>
     <PathFigure IsFilled=″True″>
      <PathFigure.Segments>
       <PathSegmentCollection>
           <StartSegment Point=″00″IsStroked=″False″/>
           <LineSegment Point=″1000″/>
           <BezierSegment Point1=″12525″Point2=″12575″
Point3=″100100″/>
           <QuadraticBezierSegment Point1=″50 50″Point2=″0100″/>
           <ArcSegment Point=″100 150″Size=″100100″
XRoration=″45″LargeArc=″False″SweepFlag=″True″/>
           <PolyLineSegment Points=″100 175 0 175″/>
           <PolyBezierSegment Points=″50 225 50 275 0 300 50 325 50
375 0 400″/>
           <PolyQuadraticBezierSegment Points=″50 450 0 500 50 550 0
600″/>
           <CloseSegment IsStroked=″True″/>
          </PathSegmentCollection>
         </PathFigure.Segments>
        </PathFigure>
       </PathFigureCollection>
      </PathGeometry.Figures>
     </PathGeometry>
    </Path.Data>
  </Path>
RadialGradient定义矩形或圆角矩形的几何图形对象。半径X和半径Y指圆角的轴对齐r径向长度:
public sealed class RectangleGeometry:Geometry
{
  public RectangleGeometry();
  public RectangleGeometry(Rect rect);
  public RectangleGeometry(
    Rect rect,
    double radiusX,
   double radiusY);
 public RectangleGeometry(
   Rect rect,RectAnimationCollection rectAnimations,
   double radiusX,DoubleAnimationCollection radiusXAnimations,
   double radiusY,DoubleAnimationCollection radiusYAnimations);
 public RectangleGeometry(
   Rect rect,RectAnimationCollection rectAnimations,
   double radiusx,DoubleAnimationCollection radiusXAnimations,
   double radiusY,DoubleAnimationCollection radiusYAnimations,
   Transform);
 public new RectangleGeometry Copy();
 [Animation(“RectAnimations”)]
 public Rect Rect{get;set;}
 public RectAnimationCollection RectAnimations{get;set;}
 [Animation(“RadiusXAnimations”)
 [DefaultValue(0.0)]
 public double RadiusX{get;set;}
 public DoubleAnimationCollection RadiusXAnimations{get;set;}
 [Animation(“RadiusYAnimations”)]
 [DefaultValue(0.0)]
 public double RadiusY{get;set;}
 public DoubleAnimationCollection RadiusYAnimations{get;set;}
}
下面的例子演示使用RadialGradient的标记:
<Path Fill=″#4000FF00″>
  <Path.Data>
    <RectangleGeometry Rect=″125 125 75 75″RadiusX=″10″
    RadiusY=″5″><RectangleGeometry>
    </Path.Data>
  </Path>
EllipseGeometry定义给出轴对齐半径X和Y长度的椭圆区域:
 public sealed class EllipseGeometry:Geometry
 {
   public EllipseGeometry();
   public EllipseGeometry(Rectangle rect);
   public EllipseGeometry(
     Point center,
     double radiusX,
     double radiusY);
   public EllipseGeometry(
     Point center,PointAnimationCollection centerAnimations,
     double radiusX,DoubleAnimationCollection radiusXAnimations,
     double radiusY,DoubleAnimationCollection radiusYAnimations);
   public EllipseGeometry(
     Point center,PointAnimationCollection centerAnimations,
     double radiusX,DoubleAnimationCollection radiusXAnimations,
     double radiusY,DoubleAnimationCollection radiusYAnimations,
     Transform transform);
   public new EllipseGeometry Copy();
   [Animation(“CenterAnimations”)]
   public Point Center{get;set;}
   public PointAnimationCollection CenterAnimations{get;set;}
   [Animation(“RadiusXAnimations”)]
   public double RadiusX{get;set;}
   public DoubleAnimationCollection RadiusXAnimations{get;set;}
  [Animation(“RadiusYAnimations”)]
  public double RadiusY{get;set;}
  public DoubleAnimationCollection RadiusYAnimations{get;set;}
}
下面的例子演示使用EllipseGeometry的标记:
<Path Fill=″#4000FF00″>
  <Path.Data>
    <EllipseGeometry Center=″50300″RadiusX=″50″
      RadiusY=″75″></EllipseGeometry>
    </Path.Data>
  </Path>
LineGeometry定义在两个点之间的直线线段并因此不包含填充区域:
 public sealed class LineGeometry:Geometry
 {
   public LineGeometry();
   public LineGeometry(Point pt1,Point pt2);
   public LineGeometry(
     Point startPoint,
     PointAnimationCollection startPointAnimations,
     point endPoint,
     PointAnimationCollection endPointAnimations);
   publlc LineGeometry(
     Point startPoint,
     PointAnimationCollection startPointAnimations,
     Point endPoint,
     PointAnimationCollection endPointAnimations,
    Transform transform);
  public new LineGeometry Copy();
[Animation(“Point1Animations”)]
public Point StartPoint{get;set;}
public PointAnimationCollection StartPointAnimations{get;set;}
 [Animation(“Point2Animations”)]
 public Point Point2{get;set;}
 public PointAnimationCollection Point2Animations{get;set;}
}
下面的例子演示使用LineGeometry的标记:
  <Path Stroke=″#4000FF00″
     StrokeThickness=″20″
     StrokeStartLineCap=″Flat″
     StrokeEndLineCap=″Triangle″
     StrokeDashCap=″Round″″
     StrokeLineJoin=″Bevel″
     StrokeMiterLimit=″100″
     StrokeDashOffset=″0″
     StrokeDashArray=″1.0 2.0″>
    <Path.Data>
      <LineGeometry StartPoint=″12525″EndPoint=″17575″></LineGeometry>
    </Path.Data>
  </Path>
成像
ImageSource是抽象类,包括用于成像管道的基本构件块。ImageSource概念上代表单一的、不变的在某个尺寸和分辨率的像素集合。例如,ImageSource可以是解码器提供的图像文件中的单一帧,或者可以是在其自己的某个ImageSource上操作的变换的结果。ImageSource不是多帧(multiframe)或动画。ImageSource是可改变的,不是因为它自己的属性可以被改变,而是因为其子-类的属性有可能可以被改变。
为了性能原因,ImageSource支持提供对图像的不受管理的访问,使用IMILBitmapSource接口。如果ImageSource的子-类不提供它,则ImageSource基类提供(使用包装类)。
namespace System.Windows.Media
{
  public abstract class ImageSource:Changeable
  }
   ///图像数据的本地格式。
   ///如果ImageSource是直接可读的,
   ///则这是当读取像素时它们所用的格式。
   public abstract PixelFormat Format{get;}
  ///ImageSource能否将其数据转换成指定的格式。
  ///如果否,格式转换器能用于进行转换。
  ///注意:为了最佳性能,ImageSource应当为PixelFormat32bppPARGB提供支持。
  public virtual bool CanConvertTo(PixelFormat targetPixelFormat)
  ///图像的宽度,以像素为单位。
  public abstract int intPixelWidth{get;}
 ///图像的高度,以像素为单位。
 ///图像的水平DPI。
 public abstract double DpiX{get;}
 ///图像的垂直DPI。
 public abstract double DpiY{get;}
 ///取图像的宽度,单位为测量单位(一英寸96个单位)。
 public double Width{get;}
 ///取图像的高度,单位为测量单位(一英寸96个单位)。
 public double Height{get;}
 ///取图像的调色板,如果有一个的话。
 ImagePalette Palette{get;}
  ///将来自图像的像素数据拷贝到具有指定步幅、
  ///起始于pixelOffset(以从起点开始的像素数量指定)的像素阵列。
  ///像素应当被拷贝到指定的pixelFormat。
  ///为查明是否支持pixelFormat,首先调用CanConvertTo。
  public void Copy(PixelFormat pixelFormat,byte[]pixels,
  int stride,int pixelOffset)
  ///将来自图像的像素数据的rect拷贝到具有指定步幅、
  ///起始于pixelOffset(以从起点开始的像素数量指定)的像素阵列。
  ///像素应当被拷贝到指定的pixelFormat。
  ///为查明是否支持pixelFormat,首先调用CanConvertTo。
  ///空rect(具有为0的宽度和/或高度),
  ///意味着忽略该rect并且拷贝整个图像。
  public abstract void Copy(IntegerRect sourceRect,PixelFormatpixelFormat,
   byte[]pixels,int stride,int pixelOffset);
  ///如果存在嵌入的缩略图,则返回它。
  ///否则,返回null。这个方法不创建图象(还没有缩略图)的缩略图。
  public virtual ImageSource EmbeddedThumbnail{get;set;}
  ///取图像的缩略图。
  ///这个方法始终返回近似与原图像相同纵横比的缩略图。
  ///
  ///如果存在嵌入的缩略图,这个方法返回缩略图,缩放到指定的尺寸。
  ///如果不存在嵌入的缩略图,图像本身被缩放到指定的尺寸。
  ///
  ///缩略图的指定宽度和高度必须都>0。
  ///选择是否使用指定的宽度值或者指定的高度值,
  ///通过确定哪一个将给出最大可能的缩略图,
  ///同时保持纵横比并且保持小于或等于宽度和高度值两者。
  ///
  ///因此,为指定你希望只使用宽度值,
  ///你将使用Int32.MaxValue用于高度值。
  public virtual ImageSource GetThumbniail(ImageSizeOptionssizeOptions);
  ///提供对这个图像的元数据的访问。
  public virtual ImageMetaData MetaData{get;set;}
  ///返回这个ImageSource的IMILBitmapSource。
  unsafe internal IntPtr BitmapSource{get;}
 }
}
ImageData是ImageSource的子-类。ImageData实现ImageSource用于若干不同的图像源:
(未输入第160页下半部分到第161页第1行的代码)
ImageData提供服务,包括在系统存储器高速缓存解码的图像,裁剪图像为指定的源rect(到高速缓存)并且使图像尺寸为指定的解码宽度和高度(到高速缓存)。对于图像解码情景,ImageData允许指定使用哪一个解码器或自动编解码器发现,基于输入流和mime类型。ImageData不支持直接从URI加载图像。加载器应当用于将URI映射成能用于构造ImageData的流。一旦构造了ImageData,其可改变的属性只有它的嵌入的缩略图、它的元数据和它的像素数据。其它属性被认为是不可变的。
ImageData的像素数据可以被改变,包括两种方法之一:(1)获得ImageData的DrawingContext并且通过DrawingContext发出命令以绘制到图像上,或者(2)使用ImageData作为VisualManager的目的地(RenderTarget)并且发出命令以呈现视件树(场景)到ImageData。在任一情况下,完成对存储器中图像的绘制,这意味着像素数据首先需要在存储器中解码和高速缓存。只有高速缓存的存储器图像被改变一图像文件本身不受影响(除非以后使用ImageEncoder将ImageData编码成图像)。
namespace System.Windows.Media
{
 ///可以用或不用高速缓存构造ImageData。
 ///如果不用高速缓存构造,则每次使用图像时将解码图像。
 ///这个方法的优点是在存储器中不存储高速缓存
 ///并且对于正在绘制的尺寸解码和过滤可以最优的。
 ///缺点是必须在每次重新绘制时进行解码。
 ///其它方法是高速缓存解码的图像。
 ///对于创建解码的、高速缓存的图像存在几种选项。
 ///它可以用特定的尺寸和特定的源rect
 ///(来自源图像的感兴趣的区域)创建。
 ///如果没有高速缓存图像则没有选项--
 ///在没有源裁剪的情况下解码它。
 ///如果高速缓存了图像,则图像的高速缓存版本变成源图像,
 ///并且原图像源将被丢弃。
 public class ImageData:ImageSource
 {
  ///从Stream(流)构造ImageData。
  ///调用者拥有流并且负责关闭它。
  public ImageData(System.IO.Stream imageStream);
  ///从Stream(流)构造ImageData。
  ///调用者拥有流并且负责关闭它。
  public ImageData(System.IO.Stream imageStream,
   CodeInfo decoderInfo,//识别要使用的解编码器(或者null)
   bool createCache,//如果false,忽略sourceRect和sizeOptions
   IntegerRect sourceRect,
   ImageSizeOptions sizeOptions
    );
   ///从像素阵列构造ImageData。
   unsafe public ImageData(
    int pixelWidth,
 int pixelHeight
 double dpiX,
 double dpiY,
 PixelFormat pixelFormat,
 ImagePalette imagePalette,
 byte[]pixels,
 int stride,
 IntegerRect sourceRect,
 ImageSizeOptions sizeOptions
 );
///从在不受管理的存储器中的像素阵列构造ImageData
///(例如DibSection)。
public ImageData (
 int pixelWidth,
 int pixelHeight
 double dpiX,
 double dpiY,
 PixelFormat pixelFormat,
 ImagePalette imagePalette,
 IntPtr pixels,//不受管理的像素阵列,例如,DibSection
 int stride,
 bool createCache,//如果false,则忽略sourceRect和sizeOptions
 IntegerRect sourceRect,
 ImageSizeOptions sizeOptions
 );
//从HBITMAP构造ImageData。
public IamgeData(
 HBITMAP hbitmap,
 HPALETTE hpalette,
 IntegerRect sourceRect,
 ImageSizeOptions sizeOptions
 );
 //从HICON构造ImageData。
 public ImageData(
  HICON hicon,
  IntegerRect sourceRect,
  ImageSizeOptions sizeOptions
  );
 //从ImageSource构造ImageData。
 public ImageData (
  ImageSource imageSource,
  bool createCache,//如果false,则忽略sourceRect和sizeOptions
  IntegerRect sourceRect,
  ImageSizeOptions sizeOptions
  );
  ///取有关用于解码图像的特定解编码器的信息
  ///(如果存在需要的解编码器并且有该信息)。
  public CodeInfo DecoderInfo{get;}
  ///取DrawingContext以在ImageData上绘制。
  public DrawingContext Open();
 }
}
ImageDecoder是提供解码器基类的抽象类。它提供确定在图像中有多少帧和枚举(或者索引)这些帧的方法。如上面提到的,图像帧各自在一ImageSource中。内建的解编码器为每个所请求的帧创建ImageData对象。内插解编码器可使用不同的子-类返回每个帧的ImageSource。ImageDecoder不是ImageSource本身,而是一个或多个ImageSource的容器。注意,图像的每个帧有可能具有不同的属性(不同尺寸,不同分辨率等等)。
namespace System.Windows.Media
{
 ///ImageDecoder本质上是图像帧的容器。
 ///每个图像帧是一个ImageSource。
 public abstract class ImageDecoder;ICollectoin,IEnumerable
 {
  ///在这个图像中的图像帧数量。
  public int Count{get;}
  ///对ICollection的访问是否同步(线程-安全)。
  public bool IsSynchronized{get;}
  ///取可以用于同步对ICollection访问的对象。
  public object SyncRoot{get;}
  ///将帧拷贝到一个阵列,从特定的阵列索引开始。
  public void CopyTo(Array array:int index);
  //返回一个计数器以反复通过图像的帧。
  public IEnumerator GetEnumerator();
  ///返回识别用于编码这个图像的解编码器-专用对象
  ///(如果解编码器支持)。
  ///这些解编码器-专用属性可以传回到相关联的编码器
  ///(如果存在一个的话)以再次取得相同类型的编码。
  public virtual object CustomEncoderProperties{get;}
  ///标识这个解编码器的信息(包括任何相关的编码器)。
  public abstract CodecInfo Info{get;}
 //取第一帧的像素格式。
 public virtual System.Windows.Media.PixelFormat Format{get;}
 ///取第一帧的像素宽度。
 public virtual int pixelWidth{get;}
 ///取第一帧的像素高度。
 public virutal int pixelHeight;
 ///取第一帧的水平dpi。
 public virtual double DpiX{get;}
///取第一帧的垂直dpi。
 public virtual double DpiY{get;}
///取图像的宽度,单位为测量单位(一英寸96个)。
public double Width{get;}
///取图像的高度,单位为测量单位(一英寸96个)。
public double Height{get;}
///如果存在第一帧的嵌入缩略图,则返回它。
///否则,返回null。这个方法不创建图像(还没有缩略图)的缩略图。
public virtual ImageSource EmbeddedThumbnail{get;}
///返回由指定的sourceRect裁剪的图像帧。
///空的源rect(宽度和/或高度为0)意味着忽略该rect并取整个帧。
public virtual ImageSource GetFrame(
 int frameIndex,
 bool createCache,
   IntegerRect sourceRect);
  ///返回应用了所有指定的裁剪和尺寸设置的图像帧。
  ///空rect(宽度和/或高度为0)意味着忽略该rect并取整个帧。
  public virtual ImageSource GetFrame(
   int frameIndex,
   bool createCache,
   IntegerRect sourceRect,
   ImageSizeOptions sizeOptions);
  ///用于返回图像的特定帧(以全尺寸)的索引器。
  ///索引必须在范围(NumFrames>索引>=0)内
  public abstract ImageSource this[int frameIndex]{get;}
  ///通过返回第一帧从ImageDecoder到ImageSource的转换。
  public static explicit operator ImageSource(ImageDecoderdecoder);
  ///提供对这个图像的元数据的只读访问。
  public abstract ImageMetaData MetaData{get;}
 }
}
为MIL提供许多内部解码器,包括ImageDecoderBmp.cs,ImageDecoderGif.cs,ImageDecoderIcon.cs,ImageDecoderJpeg.cs,ImageDecoderPng.cs,ImageDecoderTiff.cs和ImageDecoderWmp.cs。每个实现ImageDecoder和使用System.IO.Streamg来初始化解码器的单个构造函数,如下面的例子:
///如果这个解码器不能处理图像流,它将抛出异常。
public ImageDecoderJpeg(System.IO.Stream imageStream);
ImageEncoder是ImageSource(图像帧)的集合,每个ImageSource潜在地具有其自己的元数据和缩略图。还可以有与整个帧集合相关联的全局缩略图和元数据。解编码器也可选择提供对编码属性的支持,用于确定如何编码图像。帧的集合可以被保存到任何数量的指定流(一次一个)。该集合可以被清除,随后可用不同的集合填充并且再次保存。
namespace System.Windows.Media
{
 ///ImageEncoder收集一组具有其相关的缩略图和
 ///元数据的帧(ImageSource的)并将它们保存到一个指定的流。
 ///除帧-专用的缩略图和元数据之外,还可以有图像级(全局)
 ///缩略图和元数据,如果解编码器支持它的话。
 public abstract class ImageEncoder:IList:IDisposable
 {
  public void Dispose();
  ///取表示IList是否具有固定尺寸的值。
  public bool IsFixedSize{get;}
  ///取表示IList是否为只读的值。
  public bool IsReadOnly{get{return false;}}
  ///用于图像的特定帧的索引器。设置方法
  ///是该帧的代替操作。对象必须是ImageSource。
  public object IList.this[int frameIndex]{get;set;}
  public ImageSource this[int frameIndex]{get;set;}
  ///将一个帧添加到图像。
  public int IList.Add(object vlaue);
  public int Add(ImageSource imageFrame);
  ///复位编码器为空状态,无帧、缩略图、元数据或编码属性。
  public void Clear();
///确定编码器是否包含特定帧。
public bool IList.Contains(object value);
public bool Contains(ImageSource imageFrame);
///确定指定帧的索引。
public int IList.IndexOf(object value);
public int IndexOf(ImageSource imageFrame);
///这个方法在指定的帧位置插入帧,
///带有其相关联的缩略图和元数据(如果有的话)。
public void IList.Insert(int frameIndex,object value);
public void Insert(int frameIndex,ImageSource imageFrame);
///移除指定帧的第一出现。
public void ILi st.Remove(object value);
public void Remove(ImageSource imageFrame);
///从图像中移除指定帧。在列表中上移后面的帧。
public void RemoveAt(int frameIndex);
///在这个图像中的图像帧数量。
public int Count{get;}
///是否同步对ICollection的访问(线程-安全)。
public bool IsSynchronized{get;}
///取可以用于同步对ICollection访问的对象。
public object SyncRoot{get;}
///将帧拷贝到一个阵列中,从特定的阵列索引开始。
public void CopyTo(Array array,int index);
  ///返回一个计数器以重复通过图像的帧。
  public IEnumerator GetEnumerator();
  ///识别这个解编码器(包括任何相关联的解码器)的信息。
  public Codeclnfo-Info{get;}
  ///识别用于编码这个图像的属性的解编码器-专用对象。
  public object CustomEncoderProperties{get;set;}
  ///设置或者取图像的全局嵌入缩略图,如果有一个的话。
    public ImageSource EmbeddedThumbnail{get;set;}
  ///提供对这个图像的全局元数据的访问。
  public ImageMetaData MetaData{get;set;}
  ///这个解编码器是否支持具有多于一帧的图像。
  public bool SupportMultiFrame{get;}
  ///拷贝来自指定解码器的图像,包括所有的帧,所有缩略图,
  ///和所有的元数据,包括每-帧和全局数据。
  ///这完成对已经在编码器中设置的任何数据的隐含清除。
  public void CopyImage(ImageDecoder decoder);
  ///保存(编码)图像到指定的流。
  public void Save(System.IO.Stream destStream);
 }
}
为MIL提供许多内建编码器,包括ImageEncoderBmp.cs,ImageEncoderGif.cs,ImageEncoderJpeg.cs,ImageEncodePng.cs,ImageEncoderTiff.cs和ImageEncoderWmp.cs。
ImageSizeOption用于指定缩略图的尺寸和高速缓存图像的尺寸。选项包括宽度,高度,是否保持原图像的纵横比和旋转角度(90度的倍数)。
namespace System.Windows.Media
{
 ///图像的尺寸选项。所得到的图像的图像尺寸的最大值。
 ///所得到的图像仅保证具有符合指定值的宽度或高度。
 ///例如,如果想要指定高度,同时保持宽度的纵横比,
 ///则将高度设置到所想要的值,并且将宽度设置为Int32.MaxValue。
 ///
 ///如果不要保持纵横比,则使用指定的宽度和指定的高度两者,
 ///并且图像将拉伸到适合所有这些值。
 public bool PreserveAspectRation{get;set;}
 ///所得到图像的PixelWidth。见用于如何使用这个值的
 ///PreserveAspectRatio的说明。
 ///
 ///PixelWidth必须设置为比零大的值才有效。
 public int PixelWidth{get;set;}
 ///所得到图像的PixelHeight。见用于如何使用这个值的
 ///PreserveAspectRatio的说明。
 ///
 ///PixelHeight必须设置为比零大的值才有效。
 public int PixelHeight{get;set;}
 ///旋转图像的RotationAngle。只支持90的倍数。
 public Rotation RotationAngle{get;set;}
 ///尺寸选项是否有效。要有效,
 ///两者必须都大于零,且至少一个可以设置为Int32.MaxValue。
 public bool IsValid{get;}
}
}
下面提供图像和基于像素的表面的像素格式定义:
namespace System.Windows.Media
{
 ///图像和基于像素的表面的像素格式定义
 public struct PixelFormat
 {
  ///描述像素数据的每个信道的顺序
  public enum ChannelDescription
  {
   ///未定义的信道描述
   Undefined=0,
   ///单信道索引的(货盘化的(palletized))格式
   Index=1,
   ///单信道灰色格式
   Gray=2,
   ///红-绿-蓝
   RGB=3,
   ///蓝-绿-红
   BGR=4,
   ///alpha-红-绿-蓝
   ARGB=5,
   ///青-深红-黄-黑
   CMYK=6
}
///op-equality--返回两个像素格式是否相等
public static bool operator==(PixelFormat left,PixelFormatright);
///Equals--返回两个像素格式是否相等
public static bool operator==(PixelFormat left,PixelFormatright);
///op-inequality--返回两个像素格式是否不相等
public static bool operator!=(PixelFormat left,PixelFormatright);
Equals--返回这是否等于对象
public override bool Equals(Object obj);
GetHashCode--返回散列代码
public override int GetHashCode();
///这个格式的每像素位数
public int BitsPerPixel{get;}
///这个格式是否是货盘化(palletized)(索引的)格式。
public bool IsPalletized{get;}
///这个格式是否是一组灰度值。
public bool IsGray{get;}
///这个格式是否是CMYK值(青,深红,黄,黑)
public bool IsCMYK{get;}
///这个格式是否是SRGB(伽玛近似2.2)
public bool IsSRGB{get;}
///这个格式是否是线性的(伽玛为1.0)
public bool IsScRGB{gets;}
///这个格式是否已经预乘了alpha。
public bool IsPermultiplied{get;}
///描述这个格式的数据和它的顺序。
public ChannelDescription Channel{get;}
///取用于获得这个格式的红色信道的掩模。
///按leftShift数量移位掩模以取得要使用的掩模。
public void GetRedMask(out uint mask,out int leftShift);
///取用于获得这个格式的绿色信道的掩模。
///按leftShift数量移位掩模以取得要使用的掩模。
public void GetGreenMask(out uint mask,out int leftShift);
///取用于获得这个格式的蓝色信道的掩模。
///按leftShift数量移位掩模以取得要使用的掩模。
public void GetBlueMask(out uint mask,out int leftShift);
///取用于获得这个格式的alpha信道的掩模。
///按leftShift数量移位掩模以取得要使用的掩模。
public void GetAlphaMask(out uint mask,out int leftShift);
///取用于获得这个格式的各个信道的掩模。
///按leftShift数量移位掩模以取得要使用的掩模。
  public void GetRGBMask(out uint redMask,out int redLeftShift,
          out uint greenMask,out int greenLeftShift,
          out uint blueMask,out int blueLeftShift);
 }
}
要求每个解编码器(ImageEncoder和ImageDecoder)提供CodecInfo,它给出有关解编码器的信息,为其相关联的解码器/编码器提供创建实例方法,并且提供确定这个解编码器是否符合所提供的CodecFilter的方法。
namespace System.Windows.Media
{
 ///有关特定解编码器和用于创建解编码器的工厂的信息。
 ///这是从解编码器计数器返回的。
 public abstract class CodecInfo
 {
  ///由图像首部所需字节数以确定解编码器是否支持该图像。
  public abstract int RequiredHeaderSize{get;}
  ///解编码器是否支持这个图像,基于查看来自该图像的最初的
  ///RequiredHeaderSize个字节。首部必须至少包含来自该图像
  ///最初的RequiredHeaderSize个字节。
  public abstract bool IsImageSupported(byte[]header);
  ///解编码器的友好名称
  public abstract string FriendlyName{get;}
  ///解编码器支持哪些Mime类型
  public abstract string[]MimeTypes{get;}
  ///解编码器的作者。
  public abstract string CodecAuthor{get;}
  ///解编码器的版本数字。
  public abstract System.Version CodecVersion{get;}
  ///是否存在与这个解编码器相关联的解码器。
  public abstract bool HasDecoder{get;}
  ///是否存在与这个解编码器相关联的编码器。
  public abstract bool HasEncoder{get;}
  ///这个解编码器是否是内建解编码器之一。
  public bool IsBuiltIn{get;}
  ///确定这个解编码器是否符合指定的过滤器。
  ///注意:这不检查/嗅探流中的字节。
  public virutal bool MatchesFilter(CodecFilter filter);
  ///取与这个解编码器相关联的解码器的实例(如果存在的话)。
  public abstract ImageDecoder CreateDecoderInstance(System.IO.Stream.imageStream);
  //取与这个解编码器相关联的编码器的实例(如果存在的话)。
  public abstract ImageEncoder CreateEncoderInstance();
 }
}
为MIL提供内建CodecInfo对象,包括CodecInfoBmp.cs,CodecInfoGif.cs,CodecInfoIcon.cs,CodecInfoJpeg.cs,CodecInfoPng.cs,CodecInfoTiff.cs和CodecInfoWmp.cs。
由解编码器计数器使用CodecFilter基于指定的准则枚举解编码器。当查找匹配的解编码器时忽略未指定的准则。例如,如果没有设置MimeType,则考虑具有任何mime类型的解编码器。
namesDace System.Windows.Media
{
 ///用于枚举解编码器的过滤器。只有符合属性的解编码器将被枚举。
 public class CodecFilter
 {
  ///找到可以处理这个图像流的解编码器(通过嗅探该流)。
  public System.IO.Stream ImageStream{get;set;}
  ///解编码器的友好名称。
  public string FriendlyName{get;set;}
  ///解编码器是否支持这个Mime类型。
  public string MimeType{get;set;}
  ///解编码器是否符合这个作者。
  public string CodecAuthor{get;set;}
  ///解编码器的版本是否>=这个版本。
  public System.Version MinVersion{get;set;}
  ///解编码器的版本是否<=这个版本。
  public System.Version MaxVersion{get;set;}
  ///找出那些具有匹配解码器的解编码器。
  ///将这设置为false意味着不对是否存在该解编码器的
  ///解码器进行过滤。
  public bool HasDecoder{get;set;}
  ///找出那些具有匹配编码器的解编码器。
  ///将这设置为false意味着不对是否存在该解编码器的
  ///编码器进行过滤。
  public bool HasEncoder{get;set;}
  找出那些为内建(而不是内插)的解编码器。
  ///将这设置为false意味着不对该解编码器是否为
  ///内建解编码器之一进行过滤。
  public bool IsBuiltIn{get;set;}
 }
}
当构造计数器时(它的ctor是内部的),给出CodecFilter。该过滤器用于确定要枚举哪些解编码器。只枚举那些匹配过滤器(如果有的话)的解编码器。
namespace System.Windows.Media
{
 ///图像帧的计数器。
 public class ImageCodecEnumerator:IEnumerator
 {
  ///Reset--将位置复位到集合中第一个对象之前。
  ///在Reset之后对Current的任何调用之前必须调用MoveNext。
  public void Reset();
  ///MoveNext--移到集合中下一个对象。
  ///如果计数器已经过了集合的末尾则返回false
  public bool MoveNext();
  ///Current--返回集合中当前的对象
  public object Current{get;}
 }
}
ImageEffect是基于光栅的成像效果的基类。ImageEffect可以视为0或多个输入和0或多个输出的集合。对ImageEffect的输出和输入是所有类型的ImageSource。ImageEffect一般用其输入和其属性来初始化的,并且随后或者使用其输出绘制部分场景或者作为ImageEncoder的帧。内建的效果包括(但不限于)下列:ImageEffectBlur,ImageEffectFlipRotate,ImageEffectGammaCorrect,ImageEffectGlow,ImageEffectGrayscale,ImageEffectNegate,ImageEffectSharpen,ImageEffectTint。
变换
在图7中表示的Transform类的对象,可以用于缩放、旋转、转换和偏斜向量和光栅图形。派生的Transform类友好地提供使用和枚举语义。变换类层次与Matrix结构不同,后者是一个类并且支持动画和枚举语义:
  TransformCollection(枚举语义,等等)
  TransformCollect ion.AddScale(...)
  Animate MatrixTransform
Transform是抽象基类:
[TypeConverter(typeof(TransformConverter))]
public abstract class Transform:Animatable,IDisposeable
{
  internal Transform();
  public new Transform Copy();
  public static MatrixTransform CreateMatrix(Matrix matrix);
  public static TranslateTransform CreateTranslation(double x,double y);
  public static RotateTransform CreateRotation(double angle);
  public static RotateTransform CreateRotation(double angle,Point center);
  public static ScaleTransform CreateScale(double scaleX,double scaleY);
  public static ScaleTransform CreateScale(
    double scaleX,
  double scaleY,
  Point center);
public static SkewTransform CreateSkew(double angleX,double angle Y);
public static SkewTransform CreateSkew(
  double angleX,
  double angleY,
  Point center);
 //恒等变换
 public static Transform Identity{get;}
 public Matrix Value{get;}
}
TransformCollection是Transform对象的集合,其值是各个的Transform值的矩阵乘法。该值从左至右合成,匹配集合的第一和最后一个项:
  public sealed class TransformCollection:Transform,IAddChild,IList
  {
    public TransformCollection();
    public TransformCollection(int capacity);
    public TransformCollection(params Transform[]transforms);
    public TransformCollection(ICollection transformCollection);
    public new TransformCollection Copy();
    //IEnumerable
    public IEnumerator GetEnumerator();
    //ICollecfion
    public int Count{get;}
  public bool IsSynchronized{get;}
  public object SyncRoot();
  public void CopyTo(Array array,int index);
  //IList
  public bool IsFixedSize{get;}
  bool IList.IsReadOnly{get;}
  object IList.this[int index]{get;set;}
  int IList.Add(object value);
  public void Clear();
  bool IList.Contains(object value);
  int IList.IndexOf(object item);
  void IList.Insert(int index,object value);
  void IList.Remove(object value);
  public void RemoveAt(int index);
//附加的函数
 public int Capacity{get;set;}
 public Transform this[int index]{get;set;}
 public int Add(Transform transform);
 public bool Contains(Transform transform);
 public int IndexOf(Transform transform);
 public int IndexOf(Transform transform,int startIndex);
 public int IndexOf(Transform transform,int startIndex,int count);
 public int LastIndexOf(Transform transform);
 public int LastIndexOf(Transform transform,int startIndex);
 public int LastIndexOf(Transform transform,int startIndex,int count);
 public void Insert(int index,Transform transform);
 public void Remove(Transform transform);
 public void AddRange(TransformCollection transformCollection);
 public void SetRange(int index,TransformCollection transformCollection);
 public void InsertRange(int index,TransformCollection transformCollection);
 public void RemoveRange(int index,int count);
 public TransformCollection GetRange(int index,int count);
//IAddChild
void IAddChild. AddChild(Object o);
void IAddChild. AddText(string s);
public override Matrix Value{get;}
public void AddMatrix(
  double m11,
  double m12,
  double m21,
  double m22,
  double offsetX,
  double offsetY);
  public void AddMatrix(Matrix matrix);
  public void AddTranslate(double translateX,double translateY);
  public void AddRotate(double angle);
  public void AddRotate(double angle,Point center);
  public void AddScale(double scaleX,double scaleY);
  public void AddScale(double scaleX,double scaleY,Point center);
  public void AddSkew(double angleX,double angleY);
  public void AddSkew(double angleX,double angleY,Point center);
  public Transform GetOptimizedTransform();
 }
RotateTransform定义围绕一个特定的中心点(默认为0,0)旋转一个角度。角度以度为单位指定。如下是围绕点x,y的旋转角的静态矩阵表示。
1 0 0 0 1 0 - x - y 1 * cos ( angle ) sin ( angle ) 0 - sin ( angle ) cos ( angle ) 0 0 0 1 * 1 0 0 0 1 0 x y 1
public sealed class RotateTransform:Transform
public RotateTransform();
public RotateTransform(double angle);
public RotateTransform(
  double angle,
  Point center);
public RotateTransform(
  double angle,
  DoubleAnimationCollection angle,
  Point center,
  PointAnimationCollection center);
public new RotateTransform Copy();
[Animations(“AngleAnimations”)]
public double Angle{get;set;}
public DoubleAnimationCollection AngleAnimations{get;set;}
 [Animations(“CenterAnimations”)]
 public Point Center{get;set;}
 public PointAnimationCollection CenterAnimations{get;set;}
 public override Matrix Value{get;}
}
TranslateTransform(转换变换)定义在x和y方向上的轴对齐转换。如下是按偏移dx、dy的转换的静态矩阵表示。
1 0 0 0 1 0 dx dy 1
public sealed class System. Windows.Media.TranslateTransform:Transform
{
  public TranslateTransform();
  public TranslateTransform(
    double offsetx,
    double offsety);
  public TranslateTransform(
    double offsetx,DoubleAnimationCollection offsetx,
    double offsety,DoubleAnimationCollection offsety);
  public new TranslateTransform Copy();
  [Animations(“XAnimations“)]
  public double X{get;set;}
  public DoubleAnimationCollection XAnimations{get;set;}
  [Animations(“YAnimations”)]
  public double Y.{get;set;}
  public DoubleAnimationCollection YAnimations{get;set;}
  public override Matrix Value{get;}
}
ScaleTransform定义在x和y方向关于一个中心点(默认为0,0)的缩放。如下是关于点x、y的缩放sx、sy的静态矩阵表示。
1 0 0 0 1 0 - x - y 1 * sx 0 0 0 sy 0 0 0 1 * 1 0 0 0 1 0 x y 1
public sealed class ScaleTransform:Transform
{
  public ScaleTransform();
  public ScaleTransform(
    double scaleX,
    double scaleY);
  public ScaleTransform(
   double scaleX,
   double scaleY,
   Point center);
 public ScaleTransform(
   double scaleX,
   DoubleAnimationCollection scaleXAnimations,
   double scaleY,
   DoubleAnimationCollection scaleYAnimations,
   Point center,
   PointAnimationCollection center);
 public new ScaleTransform Copy();
 [Animations(“XAnimations”)]
 public double ScaleX{ get;set;}
 public DoubleAnimationCollection ScaleXAnimations{get;set;}
 [Animations(“YAnimations”)]
 public double ScaleY{get;set;}
 public DoubleAnimationCollection ScaleYAnimations{get;set;}
 [Animations(“CenterAnimations”)]
   public Point Center{get;set;}
   public PointAnimationCollection CenterAnimations{get;set;}
   public override Matrix Value{get;}
 }
SkewTransform定义按沿x和y方向角的度数的偏斜。偏斜角度以度数为单位。如下是按角度的偏斜的静态矩阵表示。
1 tan ( angleY ) 0 tan ( angleX ) 1 0 0 0 1
 public sealed class SkewTransform:Transform
 {
   public SkewTransform();
   public SkewTransform(
     double angleX,
     double angleY);
   public SkewTransform(
     double angleX,
     double angleY,
     Point center);
  public SkewTransform(
    double angleX,
    DoubleAnimationCollection angleXAnlmations,
    double angleY,
    DoubleAnimationCollection angleYAnimations,
    Point center,
    PointAnimationCollection pointAnimations);
  public new SkewTransform Copy();
  [Anirations(“AngleXAnimations”)]
  public double AngleX{get;set;}
  public DoubleAnimationCollection AngleXAnimations{get;set;}
  [Animations(“AngleYAnimations”)]
  public double AngleY{get;set;}
  public DoubleAnimationCollection AngleYAnimations{get;set;}
  [Animations(“CenterAnimations”)]
  public Point Center{get;set;}
  public PointAnimationCollection CenterAnimations{get;set;}
  public override Matrix Value{get;}
}
MatrixTransform(矩阵变换)定义一个通过其数学表示的变换。
public sealed class MatrixTransform:Transform
{
  public MatrixTransform();
  public MatrixTransform(
    double m11,
    double m12,
    double m21,
    double m22,
    double offsetX,
    double offsetY);
    public MatrixTransform(Matrix matrix);
    public new Matrix Transform Copy();
    public Matrix Matrix{get;get;}
    public override Matrix Value{get;}
  }
当用标记指定Transform类型属性时,属性系统使用Transform类型转换器来将串表示转换成适当的Transform派生对象。目前没有办法使用这个句法来描述动画的属性。
在向量图形和相应Transform结构中的句法概括如下,其中用“<>”表示的参数代表可选的参数:
* matrix(m11 m12 m21 m22 offsetX offsetY)
  - AddMatrix(m11,m12,m21,m22,offsetX,offsetY)
* translate(tx<ty>)
 - AddTranslate(tx,ty)。
 - 如果未指定ty则假定它为0。
* scle(sx<sy>)
 - AddScale(sx,sy)。
 - 如果未指定sy则假定它与sx相同。
* rotate(angle<cx><cy>)
 - AddRotate(angel,Point(cx,cy))。
 - 如果未指定cx、cy则假定它为0,0。
* skewX(angle)
 - AddSkew(angle,0)
* skewY(angle)
 - AddSkew(0,angle)
transform-list:
  wsp* transforms?wsp*
transforms:
     transform
    |transform comma-wsp+transforms
   transform:
      matrix
    |translate
    |scale
    |rotate
    |skewX
    |skdewY
matrix:
 ″matrix″wsp*″(″wsp*
    nunber comma-wsp
    number comma-wsp
    number comma-wsp
    number comma-wsp
    number comma-wsp
    number wsp*″)″
 translate:
   ″translate″wsp*″(″wsp*number(comma-wsp number)?wsp*″)″
 scale:
   ″scale″wsp*″(″wsp*number(comma-wsp number)?wsp*″)″
 rotate:
   ″rotate″wsp*″(″wsp*number(comma-wsp number comma-wsp number)?wsp*
         ″)″
  skewX:
    ″skewX″wsp*″(″wsp*number wsp*″)″
skewY:
  ″skewY″wsp*″(″wsp*number wsp*″)″
效果
效果提供一种以呈现-中心的方式改变场景的视觉内容的方法。例如,ImageEffect(基于光栅的位图效果)在部分场景的基于图像的完全合成表示上操作。效果分解成各种类型,包括ImageEffect、BlendMode和VectorEffect。
ImageEffect可以在保留模式场景中使用,通过将它应用于子-图或-Element,或者可以在独立的图像管道中使用它。一般而言,ImageEffect具有零或多个输入和零或多个输出,它们都是ImageSource类型。在立即模式图像管道中,不需要输出,因为ImageEffect可以将描述其输入属性的其它属性披露出来。例如,ImageEffect可发出彩色直方图信息或者面容-检测信息。在保留模式场景中,存在一个附加的元-输入,它提供对要应用效果的子-图的所呈现内容的访问。
///ImageEffect类是所有成像效果(模糊、灰度等)的基类。
///
///效果有可能没有任何输入,但效果必须始终具有至少一个输出。
///事物的默认实现假设这个条件。如果派生的效果将要用
///输出/多个输出来播放,则必定至少存在一个输出。
public abstract class System.Windows.Media.ImageEffect:Changeable
{
///这个构造函数允许派生类指定这个效果的输入和输出数量,
///并且这个类随后将处理输入和输出阵列,包括索引的确认。
///这默认为1和1。如果效果希望具有可变数量的输入和输出,
///则它可以传递-1用于任一个(或两个)计数,并且输入和输
///出集合将允许这样。
///最后,这些方法全是虚拟的,因此派生类可选择不委托回基类,
///在这种情况下不招致任何额外的成本。
protected ImageEffect(int inputCount,int outputCount);
///这个构造函数允许派生类提供这个效果的输入和输出数量,
///并且这个类随后将处理输入和输出阵列,包括索引的确认。
///这默认为1和1。如果效果希望具有可变数量的输入和输出,
///它可以传递-1用于任一(或两个)计数,并且输入和输出
///集合将允许这样。
///最后,这些方法都是虚拟的,所以各派生类可选择不委托回到该基类,在这种情况下不招致额外的成本。
protected ImageEffect(int inputCount,int outputCount,doubleScaleX,double ScaleY);
///这是第一个输入,并且是Inputs[0]的别名
///
///性能警告:
///如果效果的输入不是用该效果支持的格式则该效果将
///为你将该输入转换成可工作的格式。
public virtual ImageSource Input{get;set;}
///这是输入的集合。
public virtual ImageSourceCollection Inputs{get;}
///这是第一个输出,并且是Outputs[0]的别名
public virtual ImageSource Output{get;}
///这是输出的集合
public virtual ImageEffectSourceCollection Outputs{get;}
protected internal virtual ImageSource GetOutput(intoutput Index);
///这些值包含应用于这个源的水平和垂直缩放。
///存在效果需要以不同的分辨率或者不同于与当前的逻辑
///坐标空间的坐标空间来操作的机会。因而,这些属性使
///消费者能够在本地空间和ImageEffectSource空间之间映射。
protected internal virtual double GetScaleX(int outputIndex);
protected internal virtual double GetScaleY(int outputIndex);
protected internal virtual PixelFormat GetFormat(intoutputIndex);
///图像宽度,以像素为单位
protected internal virtual int GetPixelWidth(int outputIndex);
///图像高度,以像素为单位
protected internal virtual int GetPixelHeight(int outputIndex);
 ///图像水平DPI
 protected internal virtual double GetDipX(int outputIndex);
 ///图像垂直DPI
 protected internal virtual double GetDipY(int outputIndex);
 ///取用于特定输出的调色板
 protected internal virtual ImagePalette GetPalette(intoutput Index);
 ///ImageSource抽象方法实现
///PixelOffset实际上什么也不做。如果你不想在输入中从(0,0)开始,
 ///那么你的sourceRect从你想要的点开始。
 protected internal abstract void Copy(int outputIndex,
   IntegerRect sourceRect,PixelFormat pixelFormat,byte[]pixels,
  int stride,int pixelOffset);
 }
}
BlendMode是基于图像的效果的特定形式。它们可以一般以与ImageEffect相同的方式应用于保留模式场景。因而存在Element属性(“BlendMode”),还存在在Visual上的BlendMode属性,在IDrawingContext上的PushBlendMode方法和在Brush上的BlendMode属性。混合模式在源被合成时执行源和目的地颜色的组合。混合模式的例子包括乘法、加法等。VectorEffect是另一种类型的效果。
如在概述中所述,BlendMode描述控制将图像合成到另一个图像中或者到场景中的方法的操作。BlendMode可以应用于场景和Brush。每个Brush描述将源像素和目的地像素组合起来的方法,并且应用于正在合成的每个像素。BlendMode在源被缩放或者被变换之后,并且在应用了任何效果(包括Opacity)之后才被应用。注意,当应用BlendMode操作时,源和目的地处于预乘的alpha格式。为指定BlendMode,编程者可以使用在Brush静态类中指定的BlendMode之一,或者可以显式地设置源和目的地乘数。因为在一个实现中,乘数不是可扩展的并且没有参数,它们由枚举来表示:
///与每个BlendModeMultiplier相关联的四个值乘以
///由应用BlendModeMultiplier的颜色中相应信道。
///这些系数分别乘以Alpha、红、绿和蓝信道
///其中在色域内的值范围为[0..1]。
public enum BlendModeMultipliers
{
  ///Zero-(0,0,0,0)
  Zero,
  ///One-(1,1,1,1)
  One,
  ///SourceColor-(Alphasource,Redsouce,Greensource,Bluesource)
  SourceColor,
  ///InverseSourceColor-(1-Alphasource,1-Redsource,1-Greensource
  ///1-Bluesource)
  InverseSourceColor,
  ///SourceAlpha-(Alphasource,Alphasource,Alphasource,Alphasource)
  SourceAlpha,
  ///InverseSourceAlpha-(1-Alphasource,1-Alphasource,1-Alphasource
  ///1-Alphasource)
  InverseSourceAlpha,
  ///DestinationColor-(Alphadestination,Reddestination,Greendestination
  ///Bluedestination)
  DestinationColor,
  ///InverseDestinationColor-
  ///(1-Alphadestination,1-Reddestination,1-Greendestination
  ///1-Bluedestination)
  InverseDestinationColor,
  ///DestinationAlpha-(Alphadestination,Alphadestination
  ///Alphadestination,Alphadestination)
DestinationAlpha,
///InverseDestinationAlpha-
///(1-Alphadestination,1-Alphadestination,1-Alphadestination
///1-Alphadestination)
 InverseDestionaAlppha,
 ///SourceAlphaSaturate-f=min(Alphasource,1-Alphadestination),
 ///(1,f,f,f)
 SourceAlphaSaturate
}
///这个类表示源与目的地表面之间的混合操作
public sealed class BlendMode:Changeable
{
 //从所提供的BlendModeMultiplier构建定制的BlendMode
 public BlendMode(BlendModeMultiplier sourceMultiplier,
  BlendModeMultiplier destinationMultiplier);
 public new BlendMode Copy();
 public BlendModeMultiplier SourceMultiplier{get;}
 public BlendModeMultiplier DestinationMultiplier{get;}
}
///这是众知的BlendMode实例的集合
public sealed class BlendModes
{
 ///Normal--源是One,目的地是InvereSourceAlpha
 public static Normal{get;}
 ///SourceCopy--源是One,目的地是Zero
 public static SourceCopy{get;}
}
击中测试
击中测试用于拾取场景中的视件。有些高级场景包括套索选择和橡皮带选择,键盘导航(用于找出下一个要切换焦点的元素),确定元素树中的鼠标焦点,选择具有透明度的覆盖元素(如图像),“思想泡(thought bubble)”击中测试和选择文本中击中的字符。
一般而言,击中测试在核心、框架和控件上提供一致性,并且通过从控件树的顶部开始并且通过点或几何图形返回一个控件或控件集合。控件可以定义是否它被击中或者支持包括所呈现的几何图形、边界框、带外几何图形(击中区域)、图像不透明性或掩模及其自己的逻辑。控件可以在击中时返回与特定击中有关的数据(例如,线,字符位置等等)。
击中测试机制可以以有效的方式过滤击中测试结果。而且,击中测试机制为扩展到其它类型的Visual提供和分解成Visual中的子-图元提供灵活性,例如,Retained3DVisual是它的一个例子。
击中测试遍历是视件树的深度右至左遍历。存在三个参与者,击中测试器,遍历器和控件/视件。击中测试器实现两个回调,一个操舵遍历器,而另一个在某些击中视件上早结束遍历。控件实现一个虚拟方法以定义什么被击中。遍历器是系统的固定组件并且基于回调行为遍历视件树,实质上是询问每个控件该控件是否已被击中。击中是通过回调以z-顺序、顶到底方式来报告的。
在内部,击中测试因而包括对视件树的遍历。当下行时,击中测试器按照元素层关系观看过滤,例如,具有某些形状的画布,或者具有内部画布的停放面板。当击中发生时,击中测试器可以继续处理更多的击中(如果有的话),或者停止。
从击中遍历器的观点的控制流程逻辑在下面的伪代码中:
*对于每个视件,从根开始:
 -- 如果内部击中点在聚合的子击中边界内,则(例如,HitTestBounds.Contains(HitPoint))
    * 调用击中测试器委托(例如HitTestFilterDelegate)
    * 如果null或者返回继续则(例如HitTestFilterBehavior.Continue)
      * 对于每个子视件
        -- 将击中点变换到它的本地空间
        -- 针对子视件的击中测试(例如,Visual.HitTest(...))
        -- 如果子视件返回停止则返回(例如,HitTestResultBehavior.Stop)
* 如果击中点在视件内部(例如,Visual.HitTestCore(...))
  -- 调用击中测试器结果委托(HitTestResultDelegate)
  -- 或者继续或者停止(例如,HitTestResultBehavior.Continue)
击中测试器使用公有方法来起动击中测试并为控制行为提供委托。默认行为是对所有视件进行测试并且在第一个击中上返回。如果没有给出结果委托,则抛出异常。
控件通过覆盖点和几何图形的HitTestCore来决定它的击中测试逻辑。当起动击中测试时,内部视件树遍历器调用HitTestCore,实际上询问控件是否被击中。HitTestBounds反射击中区域的坚固边界并且用于优化遍历。默认的击中边界是呈现内容的边界框。
public class Visual:DependencyObject,IDisposable,IVisual
{
 //忽略非击中测试材料
 //由视件作者实现仅击中其内容的HitTestCore。
 protected virtual PointHitTestResult HitTestCore(
  PointHitTestParameters point);
 protected virtual GeometryHitTestResult HitTestCore(
  GeometryHitTestParameters geometry);
 protected virtual Rect HitTestBounds{get;}
}
public delegate HitTestFilterBehavior
 HitTestFilterDelegate(Visual visual);
public delegate HitTestFilterBehavior
  HitTestFilterDelegate(HitTestResult result);
public interface IVisual
{
 //忽略非击中测试材料
 //返回最顶上的视件击中
 public PointHitTestResult HitTest(Point point);
 //调用HitTest以起动对视件树的击中测试。
 void HitTest(
  HitTestFilterDelegate filterHitDelegate,
  HitTestResultDelegate resultHitDelegate,
  HitTestParameters hitTestParams);
}
击中测试器通过传入击中点或几何图形和HitTestParameter中的附加参数来起动击中测试。提供该类主要是要简化设计并且允许可扩展性前进。特殊的击中测试请求可以从这个类派生以将附加的信息传递给感兴趣的控件。每个控件实现对点和几何图形的特定HitTestCore。期望控件在实现其HitTestCore逻辑时考虑击中测试参数。
public abstract class HitTestParameters
{
 //公共击中测试参数
 internal HitTestParameters();
}
public class PointHitTestParameters:HitTestParameters
{
 public PointHitTestParameters(Point point);
 Point HitPoint{get;}
}
//返回两个几何图形对象之间的详细的相交信息。
enum IntersectionDetail
{
 //相交细节为空或者不要求相交细节。
  EmptyOrNotCalculated,
 //第一个几何图形完全在第二个几何图形内。
 FullyInside,
 //第二个几何图形完全包含第一个几何图形。
 FullyContains,
 //第一和第二个几何图形边缘相交。
 Intersects
}
public class GeometryHitTestParameters:HitTestParameters
{
 Public GeometryHitTestParameters(
  Geometry geometry,
  bool computeIntersectionDetail);
 public Geometry HitGeometry{get;}
 public bool ComputeIntersectionDetail{get;}
}
控件通过从HitTestResult派生返回特定的数据。例如,文本控件可能想要返回击中字符位置。PointHitTestResult包含本地坐标空间点。GeometryHitTestResult包含本地坐标空间几何图形(原击中测试的)。视件变换函数可以将击中位置映射到祖先空间。
  public abstract class HitTestResult
  {
    internal HitTestResult(Visual visual);
    public Visual Visual{get;}
  }
  public classPointHitTestResult:HitTestResult
  {
    public PointHitTestResult(Visual visual,Point point);
    pubic Point Point{get;}
  }
  public class GeometryHitTestResult:HitTestResult
    public GeometryHitTestResult(
      Visual visual,
      Geometry geometry,
      IntersectionDetail intersectionDetail);
    public Geometry Geometry{get;}
 //若GeometryHitTestParameters.IntersectionDetail则这是唯一集合
 public IntersectionDetail IntersectionDetail{get;}
}
为例示委托的使用,考虑想要最顶上的使用匿名委托的击中的击中测试器:
pubic Visual HitTest(Visual visual,Point pt)
{
Visual visualHit=null;
visual.HitTest(
  new PointHitTestParameters(pt),
  null,
  HitTestResultDelegate(HitTestResult htr){
     visualHit=htr.Visual;
     return HitTestResultBehavior.Stop;
   }
  );
  return visualHit;
 }
另一个例子是想要返回所有被击中的视件的击中测试器:
 public Visual[]HitTest(Visual visual,Point pt)
 {
  ArrayList visualsHit=new ArrayList();
  visual.HitTest(
    new PointHitTestParameters(pt),
    null,
    HitTestResultDelegate(HitTestResult htr){
       visualsHit.Add(htr.Visual);
       return HitTestResultBehavior.Continue;
     }
  );
 }
击中测试器使用枚举来控制击中测试过滤和结果行为:
  public enum HitTestFilterBehavior
  {
    //
    ContinueSkipChildren,
    ContinueSkipVisualAndChildren,
    ContinueSkipVisual,
    Continue,
    Stop
  }
HitTestFilterBehavior枚举控制过滤行为,其中指定SkipChildren击中测试这个视件,但不是它的子视件。SkipVisualAndChildren指定不要击中测试该视件或子视件。SkipVisual指定不要击中测试视件,但击中测试任何子视件。Continue指定要击中测试这个视件及其子视件。Stop指定不要击中测试视件树中的任何视件并返回到调用者。
HitTestResultBehavior枚举控制击中测试行为:
public enum HitTestResultBehavior
{
  Stop,
  Continue
}
Stop指定返回击中测试条目,跳过任何其它过滤器或者击中测试操作。Continue指定击中测试下一个视件。
尽管击中测试标识符可以用于标记确定的击中识别的特定内容,但性能很差,因为这样一个模型分解了呈现流,在击中测试时添加到遍历开销并且难以管理。在将元素和视件组合成统一的类型的情况下,粒度的基本层是视件本身,并且控件可以构建它们本身以取得它们所想要的粒度层。
控件作者通过覆盖HitTestCore和执行它自己的计算和/或使用下面描述的服务为击中编写逻辑。
下面是演示这些服务的能力的一些例子。
第一个例子演示一个控件,它具有公有的HitRegion属性,该属性表示控件的击中敏感区域。注意,击中区域不需要符合所呈现的内容,并且可由某些应用来优化。如果击中区域没有设置(_hitRegion==null),则控件听从基实现服务来确定击中。
public class HitRegionControl:Control//从视件派生。
public class HitRegionControl:Control//derives from visual.
{
  private Geometry_hitRegion;
  public Geometry HitRegion
  {
     get
  {
    return_hitRegion;
  }
  set
  {
    _hitRegion=value;
  }
}
 protected virtual PointHitTestResult HitTestCore(PointHitTestParameters
     htParams)
 {
   bool IsHit=(_hitRegion!=null)?
     _hitRegion.DoesContain(htParams.Point):IsHitRenderContents(htParams);
   return isHit?new PointHitTestResult(this,htParams.Point):null;
 }
 protected virtual GeometryHitTestResult HitTestCore(
   GeometryHitTestParamters htParams)
 {
   IntersectionDetail intersectDetail=(_hitRegion!=null)?
     _hitRegion.DoesContain(
       htParams.Geometry,
       htParams.ComputeIntersectionDetail):HitTestRenderContents(htParams);
  return(intersectDetail!=IntersectionDetail.Empty)?
    new GeometryHitTestResult(
      this,
      htParams.Geometry,
      intersectDetail):null;
 }
     proteaed virtual Rect HitTestBounds
{
    get
    {
      return(_hitRegi!=null)?_hitRegion.Bounds:GetContentBoundingBox()
    }
  }
}
 为覆盖IsHit行为,使用附加的支持服务。
 Geometry类执行对其内部区域的击中测试:
   public abstract class Geometry:Changeable
   {
     public virtual bool DoesContain(Point point);
     public virtual bool DoesContain(Geometry geometry);
     public virtual IntersectionDetail DoesContainWithDetail(Geometry geometry);
   }
视件提供受保护的函数以击中测试所呈现的内容(其本身的)。如果一个视件被保留,这将触发内容确认。这个帮助者检查存储在视件上的绘制指令流,一次一个指令,用所呈现的几何图形击中测试每一个的点或几何图形。
 public class Visual:DependencyObject,IDisposable,IVisual
 {
    protected Rect VisualDescendautBouuds{get;}
    proteeted Rect VisualContentBounds{get;}
  }
代码将返回在该点处的图像像素是否在alpha阈限之上。该点在视件空间中并且变换是到基于像素的测试发生的设备空间。
 public class ImageData:ImageSource
 {
 public virutal bool HitTestImageContents(
 HitTestParameters htParams,
 Transform transform);
 }
 动画
动画系统由两个主要组件集合组成,即定时控制引擎和动画对象集合。定时引擎是可以由展示时变行为的任何对象使用的服务,主要的例子是动画和音频或视频媒体对象。动画对象实现一组函数,将时间间隔映射到其它数据类型中,后者随后被用作其它高层对象的输入。
图形动画是通过将动画集合与呈现操作相关联来完成的。例如,IDrawingContext.DrawLine方法用笔和两个端点。可将端点之一与PointAnimation对象集合相关联,在这种情况下直线将随着时间过去而移动。同样,笔可具有相关联的ColorAnimation对象集合。在这些情况下,在呈现操作中使用的每个动画可在单独的时钟上运行,有时称为所谓的“时间线(timeline)”。一旦绘制了动画的图元,呈现系统负责以规则的间隔重新绘制场景。每次帧被呈现时,计算在场景中涉及的动画的当前值,基于流逝的时间(在大多数情况下由系统时钟测量的),随后重新绘制动画的图元。
编程动画要求既要理解由系统提供的动画对象,又要理解驱动那些动画的定时引擎。下面的术语在本章节的几个地方使用。
提供定时模型,其中时控对象加入分层定时系统,其中各个时间线具有定义其行为的属性,相对于其父亲时间线,或者对于顶层时间线,相对于根“文档”(或者“页”,或者“帧”)时间线。定时属性是一组定义对象的时间行为的参数。定时属性仅为描述性的并且没有运行时间状态。另外,定时属性是不可变的。
时间线是时序实体的实例,依照一组定时属性保持运行时间状态。时间线定义时控对象的“现在”的概念。定时树是包含在分层方式中安排的一组时间线的数据结构。在时间线之间的关系是由一组继承规则和由与各时间线相关联的定时属性定义的。
时控对象是任何展示时变行为的对象。时控对象的时间行为的描述是由一组定时属性指定,然而其运行时间定时状态是由一个或多个时间线保持的。动画函数是用特定数据类型的基值作为输入并产生同一类型的值作为其输出的函数。动画函数可以或者可以不用其它隐含或显式的输入参数,诸如时间线的当前时间值。在这方面,动画函数不可能是不变的,因为同一输入可在不同时间产生不同输出。
调节器是实现动画函数并用于修改Element的属性值、某些其它复杂对象或呈现调用的参数的对象。时控调节器是与一Timeline相关联的调节器,并且其动画函数显式地依赖于该Timeline的运行时间状态。动画是某个已知的实现动画函数集合的时控调节器。
动画集合是处理相同数据类型的调节器集合。动画集合将一个调节器的输出链接到另一个的输入,创建一个修改管道。由于整个集合用一个输入并产生一个输出,该集合本身作为调节器工作。
时间线可以看作控制时变过程如视频剪辑或动画的秒表。在时间线的属性中指定的时间是相对于某个对象的。在大多数情况下,它们相对于父亲时间线,但对于在树根的时间线,值相对于“文档时间”,其中文档时间是在起动应用时或者在导航一个页面或帧时开始的隐含时间线。以两种方法揭示在时间线中的时钟:作为从起点开始的偏移,或者作为0与1之间的进度比。后者只是当前时间与持续时间的比例。
最简单的时间线具有开始时间和持续时间。例如,具有三秒开始时间和五秒持续时间的时间线在参考时间t=0(默认地,加载应用的时刻)之后三秒“开始”并在五秒后“结束”。在那五秒期间时间线被说成“开(on)”。如果这个时间线控制一个动画,则这个动画在该时间内正在改变(例如移动),但在之前和之后是静止的。图29示出具有为三的开始时间和为五的持续时间。
可以编程时间线以重复其行为。这个重复可以指定为重复计数或重复持续时间。时间线尽可能多地经历开始到结束运行以填充所请求的计数或持续时间。如果重复计数不是整数值,则最后一次重复在中间被打断。图30示出具有Begin=3,Duration=5和RepeatDuration=17的时间线(指动画将每五秒重复,直到开始时间之后的十七秒或者二十秒后为止)。
时间线的开始时间通常相对于其父亲时间线(或者相对于文档时间),但开始时间也可相对其它时间线的开始或结束来指定。在这样一种情况下,在源时间线中每个开始(或结束)引起为目标时间线安排相应的开始。图31示出在另一个时间线之后具有3s开始时间的时间线。
当时间线到达终点时,它立即被“关”掉。在那时,它控制的时控对象停止具有在显示上的效果。例如,如果时控对象是动画,则当控制时间线到达终点时移除动画,即,它回复到它的基值。然而,存在这样的情况,即希望具有在最后值处冻结的动画的最终稳定状态。换言之,时间线从0到1在起点与终点之间前进,但在终点之后它以进度1保持“开”。这称为“填充(fill)”行为。图32表示具有Begin=3,Duration=5和Fill=Freeze的时间线。
从时间线的观点,时间线性地从进度值0流到进度值1。然而,在时间线内和在其父亲内时间通道之间的关系可以按默认的直接相互关系来改变,因为时间可在时间线中倒转,因此代替线性地从0到1的前进,它从起点处的静止加速到前进的最大速率,然后向终点处的静止减速。这产生“缓-进,缓-出(ease-in,ease-out)”的效果,用于由这个时间线控制的任何动画。
更特别地,进度/时间曲线默认地是线性的。当这个线性曲线用于控制某些动画时,用户在起点和终点处感觉到“冲击”效果,因为动画突然开始和结束。对于那些情况,时间线可以编程为使用平滑加速曲线加速从静止到最大速率的时间通道。同样,时间可编程为接近终点减速到零。加速和减速效果指定为在加速或减速阶段中花费的持续时间百分比。两个都为正,并且它们的和不超过一。图33示出具有Begin=3,Duration=10,Acceleration=0.2和Deceleration=0.4的时间线。
一个直接的时间操纵包括编程时间线以从进度值零前进到一,随后返回零。在该情况下,时间线为指定的持续时间活动两次,为“向前”部分活动一次,并为“向后”部分活动一次。图34示出具有Begin=3,Duration=5和AutoReverse=True的时间线。
时间线的表观的时间通道可以比其父亲的更快或更慢,按照一个不变的系数。默认地这个系数为1,意味着在时间线中的时间及其父亲以相同速率通过。如果代之以这个值大于一,则时间线的时间以比其父亲更快的速率前进。例如,为三的系数使时间线在起点和终点之间以比指定的持续时间快三倍的速率前进。相反,如果系统在零与一之间,则时间以较慢的速率通过。如果系统是负值,则时间线中时间始终显得相对于其父亲向后移动。注意,开始时间本身是父亲时间线的参考帧中的偏移。结果,当时间线的持续时间受速率系数的影响时,开始时间不受影响。图35示出具有Begin=3,Duration=5和Speed=0.5的时间线。
可在树结构中组织时间线。每个文档、帧或窗口具有某个隐含的“根”时间线,它可以被视为代表真实世界的挂钟时间。然而,根时间线时刻t=0是在创建该时间线时的时刻,即,在加载文档、导航帧或者打开窗口时的时刻。
给出定时系统的分层性质,它使将时间通道称为三个参考帧之一中发生有意义。简单的参考帧是由单个时间线经历的参考帧。在这个参考帧中,时间的进度值在t=0始终为0,而在t=d始终为1,其中d是简单的时间线持续时间。时间线持续时间始终在简单的参考帧中指定。父亲时间线的参考帧是作为任何给定时间线的父亲的时间线的简单参考帧。例如,时间线的Begin时间始终在父亲时间线的参考帧中指定。全局参考帧是根时间线的简单参考帧。在这个参考帧中,时刻t=5s在创建时间线之后五秒发生,而持续时间10s精确地持续真实世界的十秒。
另外,各种定时控制规则应用于定时子树,包括,如果时间线是活动的,则其父亲时间线也必须是活动的。相反,如果时间线不是活动的,则其子时间线都不是活动的,并且不能起动。如果显式地暂停时间线(通过调用ITimingControl.Pause方法),则隐含地暂停其子时间线。当恢复该时间线时,其任何不是显式地暂停的子时间线也被恢复。如果起动时间线(对于任何不同原因,包括交叉一个重复点),则复位其子时间线。
可以将另一个时间线作为一个时间线的父亲,在这种情况下定时树的形状是明确和清楚的。然而,在许多情况下,让系统自动地基于某个默认的定时父亲作为时间线的父亲是有利的。没有显式地指定其父亲的时间线称为自动-指定父亲的,并且它实际上父亲时间线取决如何使用该时间线。支持两种类型的自动-指定父亲:将父亲指定为视件父亲,或者将父亲指定为根。
时间线的视件父亲隐含地由如何使用该时间线来确定。例如,如果时间线控制颜色动画,后者接着动画用作某个视件V的背景的画刷,则V是该时间线的“视件父亲”。如果该Visual具有相关联的默认时间线,则该时间线是本例中原时间线的父亲。否则,递归地检查该Visul的父亲。始终将Visul树的根与根时间线相关联,因此如果该Visual在Visual树中,则在它之内的任何被自动-指定父亲的时间线保证在定时树中某处被指定父亲。然而,如果该Visual还不在Visual树中,则其时间线保持在定时树之外,直到诸如该Visual被插入到树中的时候为止。
默认的“根”时间线也是由视件出身定义的,除了这样一种情况,即不必使用最接近的具有时间线的Visual父亲。相反,始终将具有根出身的时间线与树中最高的Visual相关联(它可以是Frame或Window对象,或者与VisualManager相关联的根Visual。)
一旦自动为时间线指定父亲,如果发生任何改变隐含的默认父亲时间线的事件,则必须重新为其指定父亲。例如,如果时间线的直接视件父亲最初没有其自己的默认时间线,但随后设置了一个,则需要重新为该时间线指定父亲。这个重新指定父亲自动地发生。自动-指定父亲和重新-指定父亲是通过下面描述的IAnimate接口实现的。
时间线和时控对象共享许多公共的行为。例如,可以暂停或重起动动画,以及一列动画可活动或不活动。为保持一致性,时控对象实现一个或多个允许访问定时方法和属性的接口。
 ITimingControl接口是由可以在运行时间控制的时控对象实现的:
 public interface System.Windows.Media.Animation.ITimingControl
 {
 //定时属性
 double Acceleration{get;set;}
 bool AutoReverse{get;set;}
 TimeSyncValue Begin{get;set;}
 double Deceleration{get;set;}
 Time Duration{get;set;}
 TimeSyncValue End{get;set;}
 TimeEndSync EndSync{get;set;}
 TimeFill Fill{get;set;}
 TimeFill FillDefault{get;set;}
 Timeline ParentTimeline{get;set;}
 double RepeatCount{get;set;}
 Time RepeatDuration{get;set;}
 TimeRestart Restart{get;set;}
 TimeRestart RestartDefault{get;set;}
 double Speed{get;set;}
//运行时间定时状态
 int CurrentRepeat{get;}
 Time CurrentTime{get;}
 void Disable();
 void Enable();
 bool IsChanging{get;}
 bool IsEnabled{get;}
 bool IsForwardProgressing{get;}
 bool IsOverridingBaseValue{get;}
 bool IsPaused{get;}
 bool IsReversed{get;}
 double Progress{get;}
//运行时间定时控制
 void BeginIn(Time offset);
 void Disable();
 void Enable();
 void EndIn(Time offset);
 void Pause();
 void Resume();
 void Seek(Time offset,TimeSeekOrigin origin);
 void OverrideSpeed(double speed);
//事件通知
 event EventHandler Begun{add;remove;}
 event EventHandler Changed{add;remove;}
 event EventHandler Ended{add;remove;}
 event EventHandler Paused{add;remove;}
 event EventHandler Repeated{add;remove;}
 event EventHandler Resumed{add;remove;}
 event EventHandler Reversed{add;remove;}
 event EventHaudler Seeked{add;remove;}
}
下面的表概括了ITimingControl接口:
  方法,属性或事件   意义
  Acceleration   0和1之间的值代表在时间加速阶段中花费的简单持续时间的分数。这个属性与Deceleration属性的和不能超过1。
  AutoReverse   如果这个属性为“True”,则时间线从开始到结束前进,然后直接从结束前进到开始。在这种情况下,时
间线将活动两次,时间由Duration属性指定。
Begin 这个时间线应当开始的时间。默认地这个时间相对于父亲时间线的开始时间,但也可指定相对其它时间线的开始或结束时间的偏移。在后一种情况下,为其它时间线指定这一个的同一父亲时间线作为父亲。
BeginIn 触发在将来或过去时间的指定点处开始的交互。该参数在这个时间线的父亲时间线的参考帧中。如果父亲时间线不活动,则这个方法没有效果。
Begun 只要对象进入其内部状态连续改变的时段就引起。
Changed 只要它内部状态改变,就由调节器引起。
Ended 只要对象离开它内部状态连续改变的时段就引起。
CurrentRepeat 时间线的当前重复,如果它重复的话。第一次重复是重复1。如果IsOverrideingBaseValue是false则这个属性返回0。
CurrentTime 对于这个时间线的本地当前时间。如果sOverridingBaseValue为false则这个属性返回Time.Unspecified。
Deceleration 在0和1之间的值,表示在时间减速阶段中花费的简单持续时间的分数。这个属性和Acceleration属性之和不超过1。
Disable 禁止这个时间线,实际上从定时树移除它。
Duration 从开始到结束的单一时段的持续时间。
Enable 允许这个时间线,实际上将它插入定时树。如果这是自动-指定父亲的时间线而且默认父亲还未指定,则这个方法没有效果。
End 这个时间线的最大结束时间。如果这个值比Begin和Duration属性之和小,则活动时段由这个属性剪短。另外,忽略由这个属性指定的时间过去之后的全部开始(安排的或交互的)。
EndIn 触发在将来或过去的时间中指定点处的交互结束。参
数在这个时间线的父亲时间线的参考帧中。如果父亲时间线不活动,则这个方法没有效果。
EndSync 这个属性用于定义隐含的时间线持续时间,如果没有显式地设置Duration属性则使用它。隐含的时间线持续时间可由它控制的时控对象或者由以它为父亲的其它时间线来定义。
Fill 在结束时间过了之后的时间线行为。默认地,时间线只是从开始到结束才“开”,但如果将这个属性设置为“Freeze”,则时间线在过了结束时间之后保持开。在那种情况情况下,在结束时间之后进度值等于它在结束时间的情况。可能的值是Remove(全局默认)、Freeze、Hold、Transition和Auto。
FillDefault Fill属性的默认值。如果Fill属性未指定,则这个属性用于确定填充行为。另外,这个默认由作为由以这一个为父亲的时间线继承。可能的值与Fill属性相同。
IsChanging 如果时间线活动则为true,否则为false。
IsEnabled 如果时间线是定时子-树的一部分则为true,否则为false。如果这个属性为true,则这不保证这个时间线为其部分的子-树本身被允许。
IsForwardProgressing 如果在这个时间线中的进度从0到1移动(与挂钟时间相比)则返回true。这个属性考虑嵌套在潜在地倒转的时间线中的效果。如果IsOverridingBaseValue为false,则这个属性返回与这个时间线的父亲时间线所返回的相同的值。
IsOverrdingBaseValue 如果时间线活动或者在填充时段中则为true。
IsPaused 如果时间线活动但在暂停状态中则为true。
IsReversed 如果时间线在倒转的时段中则为true,如从时间线自己的本地参考帧看到的。这个属性不考虑嵌套在潜在地倒转的时间线中的效果。如果IsOverridingBaseValue为false,则这个属性返回
false。
ParentTimeline 作为这个时间线的定时父亲的时间线。这可以是对任何其它时间线的引用,或者两个特殊的参考值之一:Timeline.VisualParent或Timeline.RootTimeline。如果将这个属性设置Timeline.VisualParent,则在用于与使用它的Visual的相关联的时间线时自动指定这个时间线的父亲(如果Visual没有相关联的DefaultTimeline,则递归地检查父亲Visual)。如果将它设置为Timeline.RootTimeline,则在使用定时树的“根”时自动指定这个时间线的父亲。
Pause 暂停这个时间线及其所有子时间线。如果这个时间线不活动,则这个方法没有效果。
Paused 只要它或其子孙之一被暂停就由这个时间线引起。
Progress 时间线的当前进度值。如果IsOverridingBaseValue为false,则这个属性返回0。在所有情况下,这个属性的返回值始终是0与1之间的值,包含0和1。
RepeatCount 应当重复开始到结束时段的次数。这可以是一个分数值,也可以是特殊值float.PositiveInfinity以表示时间线应当永远重复。如果这个属性和RepeatDuration属性都被指定,则总的活动持续时间是两个中最小的一个。
RepeatDuration 应当重复开始到结束时段的时间长度。这可以隐含分数重复计数,或者它可以是特殊值Time.Indefinite以表示时间线应当永远重复。如果这个属性和RepeatCount属性都被指定,则总的活动持续时间为两个中的最小的。
Repeated 只要它的简单持续时间就由时间线引起。
Restart 当到达开始时间一秒(或更长)时时间线的行为。默认地,开始时间中断任何活动时段并且回到时间线的时刻t=0,但如果将这个属性设置为WhenNotActive,则忽略中断活动时段的开始时间。可能的值是
Always,WhenNotActive和Never。
RestartDefault Restart属性的默认值。如果未指定Restart属性,则这个属性用于确定重新起动行为。另外,这个默认由以这一个为父亲的时间线继承,除非它们已经设置了它们自己的RestartDefault属性。可能的值与用于Restart属性的相同。
Resume 恢复这个时间线及其所有子时间线。如果这个时间线不活动和暂停则这个方法没有效果。
Resumed 只它被恢复就由时间线引起。
Reversed 只要时间方向改变就由时间线引起。
Seek 改变这个时间线的当前时间,它可以在其所有子时间线上产生效果。如果这个时间线不活动,则这个方法没有效果。
Seeked 只要它的时间作为寻找操作的结果而改变就由时间线引起。
Speed 时间应当经过这个时间线的相对速度。例如,值1指正常速度,而值2指时间以两倍速度过去(并且因此,感觉到的持续时间结束在由Duration属性指定的一半。这个值可以是负值,在这种情况下时间在这个时间线中倒流,从结束到开始,好象倒转了父亲时间线。
可以通过指定动画参数到某些呈现操作或者通过将支动画添加到某些元素属性来使图形场景动画。动画是用某个任意输入集合(其中至少一个通常是时间线)并产生要传递给呈现操作的正确类型的输出的函数。例如,PointAnimation将时间线进度值转换成Point值类型。同时,用一个或多个Point值作为参数的各种呈现操作也可以接收PointAnimation代替Point,在这种情况下,在每个帧处求动画函数的值以计算要在该帧中使用的Point。
将动画分组成集合。动画集合作为管道工作,用属性的基值作为输入并且产生应当用于该属性的当前值作为其输出。集合链接零个或多个动画对象,各自支持用输入值和产生相似类型的输出的相似语义。以规则的间隔求管道的值,并且在呈现操作中使用该输出,产生动画的效果。
由于可以动画的值具有各种类型,因此也存在各种不同类型的动画。然而,所有动画按照公共的模式并且全部实现一组公共接口。动画对象被组织成三组类,即调节器、时控调节器和动画。
直接的动画在起点和终点之间内插。当起点和终点都被指定时,在动画“开”时忽略基值。当动画“关”时,属性值可回复到基值。注意,动画只要其相关联的时间线“开”就“开”。因此,可以使从-到(from)动画通过设置Fill定时属性为“Freeze”以永久地覆盖基值。图36示出在y中以From=10和To=70动画的点。
如果只指定起点或终点,但没有都指定,则属性的基值用于其它点的值。尽管这好象与先前的例子重复时,但存在一个关键差别,因为在这种情况下,基值不被忽略,而与动画合成。如果基值正在改变(因为属性正在由另一个过程改变),或者将该动画链接到另一个动画,这可以产生感兴趣的效果。
另一种指定动画函数的方法是指定从基值起的增量。这在概念上与从-到动画相似,它从基值到基值加增量内插。然而,在这种情况下起点和终点与基值合成。
如果与动画相关联的时间线设置为重复,则动画从开始到结束运行若干次。图37示出在y中From=10、By=60和RepeatCount=2动画的点。代替在每次重复时重复相同的轨道,动画可以编程为积累每次重复的效果,实质上由其自己合成。图38示出在y中以From=10、By=60、RepeatCount=2和IsAccumulating=True动画的点。
尽管从-到动画的默认行为是要忽略动画属性的基值,但这个行为可以改变为添加行为,其中从和到值都是从基值起的增量。
下面的表概括基本动画类型。
类型 输出值
From 在t=0时“From”值和在t=1时基值。
To 在t=0时基值和在t=1时“To”值。
From-To 在t=0时“From”值和在t=1时“To”值。
By 在t=0时基值和在t=1时基值与“By”值之和。
From-By 在t=0时“From”值和在t=1时“From”与“By”之和。
用基本动画,指定在起点和终点处的输出值,并使用线性内插来计算之间的值。对于更复杂的动画函数,可以指定一列值来代替。各个值相应于关键帧。在简单的情况下,这些关键帧以规则间隔出现。动画也可以编程为使用关键帧之间的步调间距。在步调内插方法中,各对关键帧之间的间距与两个关键值之间的“距离”与由动画覆盖的“总距离”之比成正比。这对于那些其类型具有有意义的“距离”概念的动画是可能的,诸如例如,浮动或点动画。在这样的情况下,在关键帧之间的内插是线性的。第三个选项是根本不内插,在这种情况下,输出值函数是离散的。图39示出在y中以KeyValues=10,90,70和各种内插方法动画的点。
对于附加的控制,可以显式地指定各个关键帧的时间。在关键帧之间的内插可以是线性或离散的。关键时间指定为总动画持续时间的百分比,并且必须覆盖整个时段。换句话说,第一个关键时间是0,而对于线性内插最后一个关键时间是1。图40示出在y中以KeyValues=10,90,50和KeyTimes=0,.2,1动画的点。
为进一步控制内插,一组三次贝塞尔曲线可以用于描述用于动画的时间曲线。这应当不会与在屏幕上显示的贝塞尔曲线混淆;该曲线用于修改定时曲线的形状,但关键帧值仍线性地在进度值上内插。这个样条内插方法增加一个过滤器,它将由与动画相关联的时间线提供的线性的0-1进度值转换成非线性0-1进度曲线。
下面的表包含动画专用属性及其意义的列表。这个列表是由所有动画对象遵循的模板。其中属性的类型是“<ValueType>”时,真实的对象将用符合动画类型的类型来揭示该属性。例如,ColorAnimation对象将这些属性的类型设为“Color”。除了下面列出的属性,动画对象支持在ITimingAttribute接口中指定的属性。
属性 类型 意义
By <ValueType> 在动画结束算计的增量值。在开始处的值或者是From值(如果指定),或者是该属性的基值。
From <ValueType> 动画的初始值。
InterpolationMethod InterpolationMethod 用于在关键值之间内插的方法。
可能的值是Discrete,Linear,Paced或Spline。
KeySpliines  KeySplineCollection 一组与KeyTimes列表相关联的贝塞尔曲线控制点,它定义控制动画的间隔步调的三次函数。这个列表必须包含比KeyTimes列表少一个元素。这个列表只在InterpolationMethod属性设置为Spline时使用。
KeyTimes  KeyTimeCollection 用于控制动画的步调的时间值列表。这个列表必须包含与KeyValues列表相同数量的元素。该列表以增加的时间值排序,并且在这个列表中第一个值必须为0并且最后一个值为1,除非InterpolationMethod设置为Discrete,在这种情况下最后一个值可以是小于或者等于1的任何值。
KeyValues <ValueType>KeyValueCollection 动画的值列表。
To <ValueType> 在动画结束处的值。
Animatable类是从Changeable类派生的。它可以由任何可使其动画或者包含动画值的对象或对象集合用作基类。Modifier、TimedModifier和Animation反而从Changeable而不是从Animatable派生,因为它们的各个属性不是动画的。
    public abstract class Animatable:Cbangeable
    {
       public abstract bool HasAnimations{get;}
       public abstract bool IsAnimating{get;}
       public abstract bool IsOverridingBaseValue{get;}
       public abstract Animatable GetCurrentValue();
       public abstract void SetDefaultParentTimeline(Timeline defaultParentTimeline);
     }
方法、属性或事件 意义
HasAnimations 如果对象可随时间变化则为true。通常,如果对象抓住任何动画集合,则这个属性为true。
IsAnimating 如果在对象中的任何动画正在改变则为true(见Modifier.IsChanging)。
IsOverridingBaseValue 如果在对象中的任何动画正在改变或者在填充状态中并因此当前在活动并且在修改对象则为true。
GetCurrentValue 返回具有与这个对象的瞬时值相同值的对象,但它不随时间过去而改变。如果DoesChange属性为false,则CurrentValue属性可返回该对象本身而不是新的拷贝。
SetDefaultParentTimeline 该时间线为任何被自动-指定父亲的时间线的父亲时间线。如果设置这个属性,则重新指定任何被自动指定父亲的时间线的父亲,但不为该时间线或这个对象创建新克隆。
Modifier类且因此TimedModifier和Animation将从Changeable而不是Animatable派生,因为它们的各个属性应当不会动画。这强加这样一个事实,即编程者应当不能够使一个动画上的From属性动画。
Modifier类不能具有值为Unchangeable的StatusOfNextUse属性。Modifier的StatusOfNextUse的默认值是ChangeableCopy,然而它也可以设置为ChangeableReference,如果用户希望重新使用Modifier。如果用户将StatusOfNextUse设置为ChangeableReference,则抛出异常,如果任何所附的Modifier没有设置ParentTimeline属性。这将阻止具有冲突的继承父亲时间线的情况。Animatable的非-动画的、非-changeable分枝可具有值为Unchangeable的StatusOfNextUse,并且可使之在使用时不changeable。在Modifier类上的属性诸如From、To或By在该Modifier的整个生存期间保持changeable。
Modifier在它们的整个存在期间是changeable的,因此MakeUnchangeable将在这些类上抛出异常。对于当前包含动画的Animatable,MakeUnchangeable将抛出异常。
如果用户签约于在Animatable类上的Changed通知,则用户将接收由属性改变或者通过动画的性质引起的改变的通知。即,当与由Animatable使用的动画相关联的Timeline在它们在所呈现的各个帧上时被寻找或者向前移动时,用户将接收已改变通知。
在独立地动画的属性(例如Opacity)或Animatable(例如,SolidColorBrush)的情况下,送到任何已经提供处理程序的用户的Changed通知将以UI线程帧速率而不是合成器帧速率发生。在此情况下动画的精确值不保证精确地出现在屏幕上的内容,尽管这些值应当接近。
如果动画是相关的或者MIL相关的,有可能取得符合将在屏幕上出现的内容的值,尽管当前不可能告诉哪一个通知相应于呈现遍并且因此哪一个反映关于要显示的值。如果定时树在呈现遍期间被改变,如经常会发生的,用户有可能接收多个通知,并且因此即使用户不太可能知道哪一个相应于在屏幕上的结果值。
调节器是实现GetValue方法的对象,它用某种类型的称为“基值(basevalue)”的对象作为输入,并且返回与输入相同类型的另一个对象。输出值取决于输入和调节器内部状态两者。特别地,这意味着用相同的输入调用GetValue多于一次不保证返回相同的输出。图形动画在每帧调用一次调节器的GetValue方法产生每个帧的新值时发生。
在一般的情况下,不保证关于GetValue的返回值,并且每次调用该方法时它可返回不同的值。消耗调节器的对象可假定这种情况并且重复地调用调节器,如在下面的例子中:
class MyObject
{
 private Modifer myModifier;
 private object myBaseValue;
 public DoSomeWork()
 {
  object currentValue=myModifier.GetValue(myBaseValue);
 DoSomethingWithCurrentValue(currentValue);
  PostCallbackToDoSomeWork();//使这个方法被再次调用
}
}
然而实际上,有时候调节器希望在给定相同输入时产生相同的输出,取决于其内部状态。调节器当它在GetValue的返回值在每次调用时不同的时段中时被说成“正在改变”。当GetValue的返回值在每次调用时相同时,它“不在改变”。如果调节器“不在改变”,则该调节器的用户可安全地高速缓存GetValue方法的返回值,并且有可能避免重复地和不必要地求GetValue方法的值,如在下面的例子中:
class MyObject
{
 private Modifier myModifier;
 private object myBaseValue;
 public Initialize()
{
  myModifier.ChangeBegun+=new EventHandler(this.OnChangeBegun);
}
public DoSomeWork()
  {
  object currentValue=myModifier.GetValue(myBaseValue);
  DoSomethingWithCurrentValue(currentValue);
  if(myModifier.IsChanging)
  {
   PostCallbackToDoSomeWork();//即刻做更多的工作
  }
  else
  {
  //什么也不做,因为调节器不准备在不久的任何时间改变。
  //如果它开始改变,则上面的委托将重新开始我们的前进循环。
  }
  }
  public OnChangeBegun()
  {
  //调节器再次正在改变,因此再次在时间表上开始进行工作
  PostCallbackToDoSomeWork();
 }
}
实现抽象Modifier类,调节器需要从它继承。这个类为除GetValue和GetUniqueInstance方法之外的一切提供默认实现:
public abstract class System.Windows.Media.Animation.Modifier
{
 public virtual Timeline ParentTimeline{get;set;}
 public virtual bool IsChanging{get;}
 public virtual bool IsOverridingBaseValue{get;}
 Modifier abstract GetUniqueModifierInstance(TimelinedefaultParentTimeline);
 object abstract GetValue(object baseValue);
public virtual bool UseBaseValue{get;}
//事件通知
 public virtual event EventHandler Changed{add;remove;}
}
下面的表概括Modifier类的语义:
方法、属性或事件 意义
Changed 每当它的内部状态改变由调节器引起。
ParentTimeline 作为在这个调节器中任何被自动指定父亲的时间线的父亲的时间线。如果设置这个属性,在这个调节器中的任何被自动指定父亲的时间线被重新指定以新的父亲时间线作为父亲。
GetUniqueInstance 返回可以保持其自己的运行时间状态与其它实例分开的这个调节器的实例。如果这个调节器包含被自动指定父亲的时间线,则返回的实例具有被指定以作为参数传递的时间线为父亲的那些时间线。
GetValue 计算这个调节器的当前输出值,基于以变元传入的基值和调节器的内部状态。当IsOverridingBaseValue属性为false,则这个函数保证返回基值。
IsChanging 如果调节器当前正在改变则为true,如果它在不改变的时段中则为false。这个标志最好结合ChangeBegun和ChangeEnded使用。如果这个标志为true,则IsOverridingBaseValue也必须为true。
IsOverridingBaseValue 如果GetValue方法的返回值当前正在受调节器的影响则为true。当这个值为false时,GetValue保证返回作为变元传递给它的同一对象。注意调节器可以覆盖基值但不改变。
UsesBaseValue 如果GetValue的返回值取决于基值则为true。如果这个属性为false,则意味着调节器完全忽略基值。如果调节器在列表中,则这个属性允许优化,其中仅调节器的子集在某些情况下必须被求值。
另外,实现一组从Modifier继承但揭示接口方法的类型-安全版本的类型-专用类。下面的例子示出FloatModifier类:
public abstract class
System.Windows.Media.Animation.FloatModifier:Modifier
{
 //类型-专用的方法
 public sealed override object GetValue(object baseValue)
 {
  return GetValue((float)baseValue);
 }
 public abstract float GetValue(float baseValue);
}
时控调节器是其行为至少部分地受Timeline对象控制的调节器。前面提到的调节器规则实施,但此外时控调节器实现ITimingControl接口以揭示控制调节器的时间线。不存在抽象的TimeModifier类。代之以从类型-专用Modifier类继承的类型-专用类。下面的例子示出FloatTimedModifier类:
public abstract class System.Windows.Media.Animation.FloatTimedModifier:
       FloatModifier,ITimingControl
{
  protected FloatTimedModifier(FloatTimedModifier example);
//FloatModifier方法、属性和事件
 public override Timeline ParentTimeline{get;set;}
 public override bool IsChanging{get;}
 public override bool IsOverridingBaseValue{get;}
 public override FloatModifier GetUniqueInstance(Timeline defaultParentTimeline);
 public override event EventHandler Changed{add;remove;}
//ITimingControl方法、属性和事件
 double Acceleration{get;set;}
 bool AutoReverse{get;set;}
 TimeSyncValue Begin{get;set;}
 double Deceleration{get;set;}
 Time Duration{get;set;}
  TimeSyncValue End{get;set;}
  TimeEndSync EndSync{get;set;}
  TimeFill Fill{get;set;}
  TimeFill FillDefault{get;set;}
  Timeline ParentTimeline{get;set;}
  double RepeatCount{get;set;}
  Time RepeatDuration{get;set;}
  TimeRestart Restart{get;set;}
  TimeRestart RestartDefault{get;set;}
  double Speed{get;set;}
  int CurrentRepeat{get;}
  Time CurrentTime{get;}
 bool IsForwardProgressing{get;}
 bool IsPaused{get;}
 bool IsReversed{get;}
 double Progress{get}
 void BeginIn(Time offset);
 void EndIn(Time offset);
 void Pause();
 void Resume();
 void Seek(Time offset,TimeSeekOrigin odgin);
 event EventHandler ChangeBegun{add;remove;}
 event EventHandler ChangeEnded{add;remove;}
 event EventHandler Paused{add;remove;}
 event EventHandler Repeated{add;remove;}
 event EventHandler Resumed{add;remove;}
 event EventHandler Reversed{add;remove;}
 event EventHandler Seeked{add;remove;}
//数据
  protected Timeline Timeline;
}
注意Modifier和ITimingControl接口具有某些相似的方法、属性和事件。TimedModifier揭示用于那些的单一实现。TimedModifier通过转发所有调用到控制Timeline而免于实现ITimingControl,尽管不要求这么做。由类型-专用TimedModifier实现提供的ITimingControl的默认实现将调用转发到控制Timeline。
动画是实现特定动画函数的时控调节器:
public sealed class
 System.Windows.Media.Animation.FloatAnimation:
 FloatTimedModifier
{
 public FloatAnimation(float from,float to,Time duration);
 public FloatAnimation(float from,float to,Time duration,TimeFill fill);
 public FloatAnimation(float to,Time duration);
 public FloatAnimation(float to,Time duration,TimeFill fill);
 //继承所有floatTimedModifier方法、属性和事件,加上下面的:
 public float By{get;set;}
 public float From{get;set;}
 public InterpolationMethod InterpolationMethod{get;set;}
 public bool IsAccumulating{get;set;}
 public KeySplineEnumerator KeySplines{get;set;}
 public KeyTimeEnumerator KeyTimes{get;set;}
 public FloatKeyValueEnumerator KeyValues{get;set;}
 public float To{get;set;}
}
动画集合是动画对象列表(从<Type>Modifier继承的),其中来自第一对象的GetValue方法的输出用作在第二对象止的GetValue方法的基值参数,等等。为了灵活性,包含在动画集合中的对象实际上是类型-专用Modifier类型的。集合总体上支持GetValue方法,它好象IModifier.GetValue。实际上,动画集合支持大多数IModifier接口,但它们实际上不实现IModifier,因为它们不支持“UsesBaseValue”属性(这个属性对于集合整体上始终假定为“true”)。
public sealed class
System.Windows.Media.Animation.FloatAnimationCollection:
 ICollection
{
 public Timeline DefaultParentTimeline{get;set;}
 public bool IsChanging{get;}
 public bool IsOverridingBaseValue{get;}
 public FloatAnimationCollection GetUniqueInstance(Timeline
  defaultParentTimeline);
 public float GetValue(float baseValue);
 //事件通知
 public event TimeEventHandler ChangeBegun{add;remove;}
 public event TimeEventHandler Changed{add;remove;}
 public event TimeEventHandler ChangeEnded{add;remove;}
 //支持的ICollection MPE
 public FloatModifier this[int index]{get;}
}
从动画集合激发的事件是接合的。
路径动画是特殊化的TimedMatrixModifier类。MatrixModifier可以连同MatrixTransform一起使用。MatrixTransform具有Matrix属性和MatrixAnimations属性,并且因为PathAnimation是MatrixModifier,它可以用作MatrixAniamtion。
public sealed class System.Windows.Media.Animation.PathAnimation:
  TimedMatrixModifier
{
  public PathGeometry PathGeometry {get;set;}
  public bool DoesRotateWithTangent{get;set;}
}
方法、属性或事件 意义
Geometry 这可以是任何几何图形。对于椭圆,选择适当的起点用于进度0。如果几何图形具有许多子几何图形,将依次按在几何图形内定义它们的顺序沿其各自路径移动。
DoesRotateWithTangent 如果这个属性设置为false,则无旋转地沿几何图形路径移动。如果设置为true,则对象将旋转以符合在任何给定位置处的路径切线。
标记用法:
<Canvas>
 <Canvas.TransformEffect>
  <MatrixTransform><!--default Matrix base value is identity-->
   <MatrixTransform.Matrix>
    <PathAnimation Begin=”0”Duration=”10”DoesRotateWithTangent=”true”/>
     <PathAnimation.Geometry>
      <PathGeometry>...</PathGeometry>
     </PathAnimation.Geometry>
    </PathAnimation>
   </MatrixTransform.Matrix>
  </MatrixTransform>
 </Canvas.TransformEffet>
</Canvas>
可以形成动画的每一资源、方法或对象按照许多规则,包括它实现Animatable接口。对于每一称为“Foo”类型为“Bar”能动画的属性(或参数),存在称为“FooAnimations”类型为“BarAnimationCollection”的另一属性(或者参数)。只要动画是希望的,就使用动画集合。不直接使用基本Modifier或动画对象,因为这排除了动画合成。
可以通过添加动画集合到各个属性来使资源形成动画。下面的例子示出如何用动画颜色创建SolidColorBrush:
 ColorAnimation anim=new ColorAnimation();
 animBuilder.From=new Color(1.0f,0.0f,0.0f,0.0f);
 animBuilder.Begin=new Time(0);
 animBuilder.To=new Color(1.0f,1.0f,0.0f,0.0f);
 animBuilder.Duration=new Time(1000);
 animBuilder.AutoReverse=true;
 animBuilder.RepeatDuration=Time.Indefinite;
 SolidColorBrush brush=new SolidColorBrush();
 brush.Color=new Color(1.0f,0.0f,0.0f,0.0f);
 brush.ColorAnimations=anim;
动画资源可以在呈现操作中使用或者用作Effect属性的值。
可能通过添加动画集合到绘制上下文方法调用或者通过使用动画资源来使呈现操作动画。下面的例子示出如何使动画的不透明性值进栈到绘制上下文:
 FloatAnimation anim=new FloatAnimation();
 anim.From=0.0f;
 anim.Begin=Time.Immediately;
 anim.To=1.0f;
 anim.Duration=new Time(1000);
 anim.Fill=TimeFill.Freeze;
 myDrawingContext.PushOpacity(0.0f,anim);
可以通过添加动画集合到Effect属性来使元素动画。下面的例子示出在C#中如何使按钮的宽度动画:
LengthAnimation anim=new LengthAnimation();
anim.From=new Length(50);
anim.Begin=Time.Immediately;
anim.To=new Length(100);
anim.Duration=new Time(1000);
anim.Acceleration=0.2;
anim.Deceleration=0.2;
anim.Fill=TimeFill.Freeze;
myButton.Width=new Length(50);
myButton.WidthAnimations=anim;
下面示出在XAML中的相同例子:
<Button ID=”myButton”Width=”50”>
  <Button.Width>
    <LenthAnimationCollection>
      <LengthAnimation
        From=″50″
        Begin=″Immediately″
        To=″100″
        Duration=″1″
        Acceleration=″0.2″
        Deceleration=″0.2″
        Fill=″Freeze″
      />
    </LenghAnimationCollection>
   </Button.Width>
 </Button>
只要使用动画(或者动画的资源),就克隆(以浅的有效方式)动画(或资源)来为目的地提供唯一的可独立控制的时间线。这个行为的副作用是原动画不是视件场景的一部分,并且因此它不响应于通过ITimingControl接口的控制调用。为实现这个效果,调用的代码首先使用动画且然后读回该动画。随后可以高速缓存读回的值并用于定时控制。下面的例子示出想要控制动画的代码可遵循的模式:
private FloatAnimation myOpacityAnimation;
public void Initialize()
{
 FloatAnimation anim=new FloatAnimation();
 //设置Begin属性为Indefinite,因为想要交互地而非自动地起动这个动画。
 anim.Begin=Time.Indefinitely;
 anim.From=1.0f;//完全透明
 anim.Duration=new Time(500);//半秒
 anim.To=0.5f;//半透明
 anim.AutoReverse=true;
 //使拥有的某元素的不透明性动画化
 myElement.Opacity=1.0f;
 myElement.OpacityAnimations=anim;
 //错误:下面的行没有想要的结果:
 //myOpacityAnimation=animetion;
//
 //这个行高速缓存动画“模板”,不是控制元素不透明性的实际动画。
 //这高速缓存正确的动画一实际使用的动画:myOpacityAnimation=(FloatAnimation)myElement.OpacityAnimations[0];
}
public void OnSomeEvent()
{
 //只要检测到某事件,“闪烁”该元素
 myOpacityAnimation BeginIn(0);
}
用户将使用AnimationEffect作为基类创建新类以实现AnimationEffect。用户也将需要创建它们的AnimationEffect的生成器。
    public abstract class AnimationEffect:Changeable
    {
      protected AnimationEffeet(AnimationEffect effect);
      public abstract AnimationEffect GetUniqueInstance(Timeline
           defaultParentTimeline);
      protected void Invalidate();
      protected void InvalidatePassive();
      protected bool IsInvalid{get;}
      protected Element Element{get;}
      protected virtual void AttachImpl();
      protected virtual void DetachImpl();
      protected virtual void PreLayoutReadImpl();
      protected virtual void PreLayoutWriteImpl();
      protected virtual void PostLayoutReadImpl();
    }
方法、属性或事件 意义
Invalidate 用户将在它们想要将它们的AnimationEffect放在下一个RenderQueueItem期间要处理的AnimationEffect列表中时调用这个并且它们想要确信安排了RenderQueueItem。在RenderQueueItem的开始处复位无效动画列表。
InvalidatePassive 用户将在它们想要它们的AnimationEffect放在下一个RenderQueueItem期间要处理的AnimationEffect列表中时调用这个,但它们不想要使得RenderQueueItem被安排。
IsInvalid 如果动画当前在下一个RenderQueueItem期间要处理的AnimationEffect列表中则返回true。因为已经调用了Invalidate,因此它可以为true。
Element 这是AnimationEffect所附着于的Effect。如果该
AnimationEffect附着于Effect,则将抛出异常。用户应当不进行任何设置,直到已经调用了OnAttach。
AttachImpl 当AnimationEffect附着于元素时,自动地克隆它并且将新克隆添加到该元素上的AnimationEffect集合以及让OnAttach被调用。这里,将设置在AnimationEffect上的受保护的Effect属性。如果用户已经将AnimationEffect添加到集合,只有新的AnimationEffect将让OnAttach被调用。不保证当OnAttach被调用时Effect将设置其标记属性或者该Effect的子Effect将都在原地。克隆AnimationEffect。尽管Effect可以在调用每个函数时被传递给AnimationEffect,但不能将它传递给来自其它元素(它们是该AnimationEffect最需要它的地方)事件的事件处理程序。AnimationEffect可在其它元素上设置事件处理程序但将仍需要知道它被赋值给这个Effect。
DetachImpl 在使AnimationEffect从Effect分开时在该AnimationEffect上调用这个。
PreLayoutReadImpl 如果AnimationEffect在运行RednerQueueItem中的布局之间为灰暗时在该AnimationEffect上调用这个。这是在该AnimationEffect应当读取它需要的值的时候。读和写分开的原因是读使布局立即运行并且如果每一AnimationEffect依次读写它将减慢整个处理过程的速度。
PreLayoutWriteImpl 如果AnimationEffect在运行RenderQueueItem中的布局之前为灰暗,则在该AnimationEffect上调用这个。尽管不保证处理AnimationEffect的顺序,但保证所有灰暗的AnimationEffect将在调用这个之前已经调用了OnPreLayoutRead。
PostLayoutReadImpl 如果AnimationEffect在运行RenderQueueItem中的布局之后为灰暗则调用这个。如果没有设备
IsAlwaysDirty,则在这个AnimationEffect上的灰暗标志将已经被设置为false并且已经从在下一个RenderQueueItem期间要处理的AnimationEffect列表中移除它。如果AnimationEffect愿意保持灰暗,则设置IsAlwaysDirty标志会有效得多。
图元类型
在MIL中的基长度单位是双精度型,由此其它图元类型和API基于双精度型。通常这些双精度型是作为最初等于一英寸的1/96的用户单位来求值的。对于颜色,各个颜色信道由浮点型表示,而不双精度型。对于角度测量,双精度值单位为度。当浮点型或双精度型作为时间测量求值时,假定为秒。
Time结构代表在时间上或者一段时间的一个特定点。另外,称为“Indefinite”的特殊时间值或者代表在将来无穷时间上的点或者代表在无限长的时间段上的点。时间值设计为在属性系统中使用,因此称为“Unspecified”的特殊值可用于清除属性,或者显式地表示该属性未被设置。时间值内部存储为整数计数。
time:
        (full-clock-value|partial-clock-value|timecount-value|special-value)
full-clock-value:
        hours″:″minutes″:″seconds(″.″fraction)?
partial-clock-value:
        minutes″:″seconds(″.″fraction)?
timecount-value:
        timecount(″.″fraction)?(metric)?
special-value:
        (“Iudefinite”|“Unspecified”)
metric:
        ″h″|″min″|″s″|″ms″
hours:
        digit+
minutes:
        2digit
seconds:
       2digit
fraction:
       digit+
timecount:
       digit+
2digit:
       digit digit
digit:
       ″0″|″1″|″2″|″3″|″4″|″5″|″6″|″7″|″8″|″9″
除了上面的语法,注意“minutes”和“seconds”必须在“00”到“59”的范围内指定才被认为有效。而且,如果使用无单位的“timecount-value”,则假定该值以秒为单位。下面是一些Time值及其意义的例子:
Time  值
02:30:03  2小时,30分钟3秒
50:00:10.25  50小时,10秒250毫秒
02:33  2分钟33秒
00:10.5  10秒500毫秒
3.2h  3小时12分钟
45min  45分钟
30s  30秒
5.45ms  5.45毫秒
12.467  12秒467毫秒
1d  1日
Time结构用于存储单个Time值:
public struct System.Windows.Media.Animation.Time:IComparable
{
  public Time(int milliseconds);
  public bool IsFinite{get;}
  public static Time Abs(Time t);
  public int CompareTo(Time other);
  public override bool Equals(object obj);
  public override int GetHashCode();
  public static Time Max(Time a,Time b);
  public static Time Min(Time a,Time b);
  public override string ToString();
  public static Time operator+(Time a,Time b);
  public static Time operator-(Tine t);
  public static Time operator-(Time a,Time b);
  public static Time operator*(double s,Time t);
  public static Time operator*(Time t,double s);
  public static Time operator/(Time t,double s);
  public static double operator/(Time a,Time b);
  public static Time operator%(Time a,Time b);
  public static bool operator=(int n,Time time);
  public static bool operator=(Time time,int n);
  public static bool operator=(Time a,Time b);
  public static bool operator!=(int n,Time time);
  public static bool operator!=(Time time,int n);
  public static bool operator!=(Time a,Time b);
  public static bool operator>=(Time a,Time b);
  public static bool operator<=(Time a,Time b);
  public static bool operator>(Time a,Time b);
  public static bool operator<(Timc a,Time b);
  public static readonly Time Immediately;
  public static readonly Time Indefinite;
  public static readonly int MaxValue;
  public static readonly int MinValue;
  public static readonly Time Unspecified;
}
下面阐述其它基本类型,其中使用下面的符号:
·*:0或更多
·+:1或更多
·?:0或1
·{n}:n次
·():分组
·|:分开替换者
·双引号围绕的文字
wsp:
    whitespace+
digit:
    ″0″|″1″|″2″|″3″|″4″|″5″|″6″|″7″|″8″|″9″
hex-digit:
    digit|″a″|″A″|″b″|″B″|″c″|″C″|″d″|″D″|″e″|″E″|″f″|″F″|
digit-sequence:
    digit+
sign:
    ″-″|″+″
  exponent:
    (″e″|″E″)sign?disit-sequence
 fractional-constant:
    (digit-sequence?″.″digit-sequence)|(digit-sequence″.″)
fioatitmg-point-constant:
    (fractional-constant exponent?)|(digit-sequence exponent)
integer-constant:
    digit-sequence
comma:
    ″,″
    comma-wsp:
    (wsp comma?wsp*)|(commawsp*)
number:
    (sign?(integer-constant|floating-point-constant))|“Unset”
number-wsp:
    number wsp*
coordinate:
    number-wsp
coordinate-pair:
    coordinate comma-wsp coordinate
coordinate-pairs:
    (coordinate-pair comma-wsp)*coordinate-pair
filename:
      wsp*(″valid-filename-char+″|valid-filename-char-no-whitespace)wsp*
  用于颜色的标记句法:
  numeric-color:
        ″#″(hex-digit{3}|hex-digit{4}|hex-digit{6}|hex-digit{8})
  color:
        numeric-color|[a-zA-Z]+
  Color对象包含静态成员,包括许多众知的颜色如Red或Blue:
    public sealed class Colors
    {
      public static Color AliceBlue{get;}
      public static Color AntiqueWhite{get;}
      public static Color Aqua{get;}
      public static Color Aquamarine{get;}
public static Color Azure{get;}
public static Color Beige{get;}
public static Color Bisque{get;}
public static Color Black{get;}
public static Color BlanchedAlmond{get;}
public static Color Blue{get;}
public static Color BlueViolet{get;}
public static Color Brown{get;}
public static Color BurlyWood{get;}
public static Color CadetBlue{get;}
public static Color Chartreuse{get;}
public static Color Chocolate{get;}
public static Color Coral{get;}
public static Color CornflowerBlue{get;}
public static Color Cornsilk{get;}
public static Color Crimson{got;}
public static Color Cyan{get;}
public static Color DarkBlue{get;}
public static Color DarkCyan{get;}
public static Color DarkGoldenrod{get;}
public static Color DarkGray{get;}
public static Color DarkGreen{get;}
public static Color DarkKhaki{get;}
public static Color DarkMagenta{get;}
public static Color DarkOliveGreen{get;}
public static Color DarkOrange{get;}
public static Color DarkOrchid{get;}
public static Color DarkRed{get;}
public static Color DarkSalmon{get;}
public static Color DarkSeaGreen{get;}
public static Color DarkSlateBlue{get;}
public static Color DarkSlateGray{get;}
public static Color DarkTurquoise{get;}
public static Color DarkViolet{get;}
public static Color DeepPink{get;}
public static Color DeepSkyBlue{get;}
public static Color DimGray{get;}
public static Color DodgerBlue{get;}
public static Color Firebrick{get;}
public static Color FloralWhite{get;}
public static Color ForestGreen{get;}
public static Color Fuchsia{get;}
public static Color Gainsboro{get;}
public static Color GhostWhite{get;}
public static Color Gold{get;}
public static Color Goldenrod{get;}
public static Color Gray{get;}
public static Color Green{get;}
public static Color GreenYellow{get;}
public static Color Honeydew{get;}
public static Color HotPink{get;}
public static Color IndianRed{get;}
public static Color Indigo{get;}
public static Color Ivory{get;}
public static Color Khaki{get;}
public static Color Lavender{get;}
public static Color LavenderBlush{get;}
public static Color LawnGreen{get;}
public static Color LemonChiffon{get;}
public static Color LightBlue{get;}
public static Color LightCoral{get;}
public static Color LightCyan{get;}
public static Color LightGoldenrodYellow{get;}
public static Color LightGray{get;}
public static Color LightGreen{get;}
public static Color LightPink{get;}
public static Color LightSalmon{get;}
public static Color LightSeaGreen{get;}
public static Color LightSkyBlue{get;}
public static Color LightSlateGray{get;}
public static Color LightSteelBlue{get;}
public static Color LightYellow{get;}
public static Color Lime{get;}
public static Color LimeGreen{get;}
public static Color Linen{get;}
public static Color Magenta{get;}
public static Color Maroon{get;}
public static Color MediumAquamarine{get;}
public static Color MediumBlue{get;}
public static Color MediumOrchid{get;}
public static Color MediumPurple{get;}
public static Color MediumSeaGrreen{get;}
public static Color MediumSlateBlue{get;}
public static Color MediumSpringGreen{get;}
public static Color MediumTurquoise{get;}
public static Color MediumVioletRed{get;}
public static Color MidnightBlue{get;}
public static Color MintCream{get;}
public static Color MistyRose{get;}
public static Color Moccasin{get;}
public static Color NavajoWhite{get;}
public static Color Navy{get;}
public static Color OldLace{get;}
public static Color Olive{get;}
public static Color OliveDrab{get;}
public static Color Orange{get;}
public static Color OraugeRed{get;}
public static Color Orchid{get;}
public static Color PaleGoldenrod{get;}
public static Color PaleGreen{get;}
public static Color PaleTurquoise{get;}
public static Color PaleVioletRed{get;}
public static Color PapayaWhip{get;}
public static Color PeachPuff{get;}
public static Color Peru{get;}
public static Color Pink{get;}
public static Color Plum{get;}
public static Color PowderBlue{get;}
public static Color Purple{get;}
public static Color Red{get;}
public static Color RosyBrown{get;}
public static Color RoyalBlue{get;}
public static Color SaddleBrown{get;}
public static Color Salmon{get;}
public static Color SandyBrown{get;}
public static Color SeaGreen{get;}
public static Color SeaShell{get;}
public static Color Sienna{get;}
public static Color Silver{get;}
public static Color SkyBlue{get;}
public static Color SlateBlue{get;}
public static Color SlateGray{get;}
    public static Color Snow{get;}
    public static Color SpringGreen{get;}
    public static Color SteelBlue{get;}
    public static Color Tan{get;}
    public static Color Teal{get;}
    public static Color Thistle{get;}
    public static Color Tomato{get;}
    public static Color Transparent{get;}
    public static Color Turquoise{get;}
    public static Color Violet{get;}
    public static Color Wheat{get;}
    public static Color White{get;}
    public static Color WhiteSmoke{get;}
    public static Color Yellow{get;}
    public static Color YellowGreen{get;}
  }
下面阐述点结构:
public struct System.Windows.Point
{
 public Point();//初始化为0,0
 public Point(double x,double y)
 public static Boolean Equals(Point point1,Point point2)
 public virtual Boolean Equals(Object o)
 public DoubleX{get;set;}
 public DoubleY{get;set;}
 public virtual Int32 GetHashCode()
 public static Point operator+(Point point,Vector vector)
 public static Boolean operator==(Point point1,Point point2)
 public static Boolean operator!=(Point point1,Point point2)
 public static Point operator*(Point point,Matrix matrix)
 public static Point operator-(Point point,Vector vector)
 public static Vector operator-(Point point1,Point point2)
 //这将用X和Y的绝对值,因为Size不能为负值
 public static explicit operator Size(Point point)//
 public static explicit operator Vector(Point point)
 public static Point Add(Point point,Vector vector)
 public static Point Multiply(Point point,Matrix matrix)
 public void Offset(Double dx,Double dy)
 public static Point Substract(Point point,Vector vector)
 public static Vector Substract(Point point1,Point point2)
 public virtual String ToString()
}
点对象的标记句法:
point:
 coordinate-pair
下面阐述Vector对象:
public struct System.Windows.Vector
{
 public Vector();//初始化为0,0
 public Vector(double x,double y);
 public double X{get;set;}
 public double Y{get;set;}
 public static Boolean Equals(Vector vector1,Vector vector2)
 public virtual Boolean Equals(Objeot obj)
 public Double Length{get;}
 public Double LengthSquared{get;}
 public Double X{get;set;}
 public Double Y{get;set;}
 public virtual Int32 GetHashCode()
 public static Point operator+(Vector vector,Point point)
 public static Vector operator+(Vector vector1,Vector vector2)
 public static Vector operator/(Vector vector1,Vector vector2)
 public static Boolean operator==(Vector vector1,Vector vector2)
 public static Boolean operator!=(Vector vector1,Vector vector2)
  //返回点积:vector1.X*vector2.X+vector1.Y*vector2.Y
public static Double operator*(Vector vector1,Vector vector2)
 public static Vector operator*(Double scalar,Vector vector)
 public static Vector operator*(Vector vector,Matrix scalar)
 public static Vector operator*(Vector vector,Matrix matrix)
 public static Vector operator-(Vector vector1,Vector vector2)
 public static Vector operator-(Vector vector)
 //这将用X和Y的绝对值,因为Size不能是负的
 public static explicit operator Point(Vector vector)
 public static explicity operator Size(Vector vector)
 public static Vector Substract(Vector vector1,Vector vector2)
 public static Double Multiply(Vector vector1,Vector vector2)
 public static Vector Multiply(Double scalar,Vector vector)
 public static Vector Multiply(Vector vector,Double scalar)
 public static Vector Multiply(Vector vector,Matrix matrix)
 public static Vector Divide(Vector vector,Double Scalar)
 public static Point Add(Vector vector,Point point)
 public static Vector Add(Vector vector1,Vector vector2)
 public void Normalize()
  //返回将v1旋转到v2所要求的角度,以度为单位
  //这将返回在(-180,180]度之间的值
 public static Double AngleBetween(Vector vector1,Vector vector2)
  public static Double CrossProduct(Vector vector1,Vector vector2)
  //返回Determinant:vector1.X*vector2.Y-vector1.Y*vector2.X
 public static Double Determinant(Vector vector1,Vector vector2)
 public virtual String ToString()
}
Vector对象的标记句法:
size:
 coordinate-pair
注意,size不是Vector,因而不能加、减或变换它。而且,size不能具有负的宽度或高度。如果作出设置负值的尝试将抛出ArgumentException。
关于矩形,使用名称Rect代替Rectangle以便不与Rectangle元素冲突。尽管有可能指定负宽度和高度,但没有标准的方法来标准化矩形并且在矩形上的许多操作可给出非直觉的结果。Rect的Width和Height不能设置为非负值。如果将这样的值传递给构造函数,则将标准化结果。如果将Width或Height设置为负值,则这将导致ArgumentException。
Rect包含在它之中的点,以及位于其边缘的所有点。因而,包括Rect的边缘。因此,宽度0或高度0的Rect不是空的,因为它包含在由Rect代表的1-维直线线段上存在的点集。如果Width和Height都是0,则Rect包含在Location处的一个Point。这意味着真正的空Rect是特殊值,并且可以通过静态EmptyRect属性访问。EmptyRect的Width和Height属性将返回负无穷大(唯一的情况或者可以是负值),X和Y属性将返回正无穷大,并且这些属性都不能修改。这保证没有“空”宽度但有正常高度,或者相反。
public struct System.Windows.Rect
{
 public Rect();//设置所有值为0
 public Rect(Point location,Size size);
public Rect(double x,double y,double width,double height);
//它们两者都将标准化矩形
public Rect(Point point1,Point point2);
public Rect(Point point,Vector vector);
public static Rect FromLTRB(double left,double top,double right,double bottom);
public static Rect Empty{get;}//返回Empty Rect
public bool IsEmpty{get;}
public static Rect Infinite{get;}
public Point Location{get;set;}
public Size Size{get;set;}
public double X{get;set;}
public double Y{get;set;}
public double Width{get;set;}
public double Height{get;set;}
public double Left{get;}//X的别名
public double Top{get;}//Y的别名
public double Right{get;}//X+Width
public double Bottom{get;}//Y+Height
public Point TopLeft{get;}
public Point TopRigbt{get;}
public Point BottomLeft{get;}
public Point BottomRight{get;}
public Point Center{get;}
public bool Contains(Point point);
public bool Contains(Reet rect);
public bool Contains(double x,double y);
public bool IntersectsWith(Rect rect);
public void Intersect(Rect rect);
public static Rect Interseet(Rect rect1,Reet rect2);
public void Union(Rect rect);
public static Rect Union(Rect rect1,Reet rect2);
public void Union(Point point);
public static Rect Union(Rect rect,Point point);
public void Offset(Vector offset);
public void Offset(double dx,double dy);
public static Rect Offset(Rect rect,Vector offset);
public static Rect Offset(Rect rect,double dx,double dy)
public void Inflate(Size size);
//如果-width>Width*2或者-height>Height*2,则Rect变成Empty
public void Inflate(double width,double height);
public static Rect Inflate(Rect rect,double width,doublelength);
public static Rect Inflate(Rect rect,Size size);
//变换4个角并且设置新的轴对齐rect。
public void Transform(Matrix matrix);
public static Rect Transform(Rect rect,Matrix matrix);
public virtual Boolean Equals(Rect rectangle1,Rect rectangle2)
public virtual Boolean Equals(Object o)
public virtual Int32 GetHashCode()
public static Boolean operator==(Rect rectangle1,Rectrectangle2)
public static Boolean operator!=(Rect rectangle1,Rectrectangle2)
}
如所示的,rect提供许多方法。如果实例等于Empty Rect则IsEmpty返回true。FromLTRB方法实质上返回用(left,top,right-left,bottom-top)初始化的矩形。然后如果Rect不是Empty,p.x>=r.x,p.x<=r.x+r.width,p.y>=r.y和p.y<=r.y+r.height,则Contains方法返回true。这意味着如果矩形没有负宽度或高度这个方法将返回false。
如果Rect都不是Empty,r1.x<=r2.x+r2.width,r2.x<=r1.x+r1.width,r1.y<=r2.y+r2.height,则IntersectsWith返回true。两个矩形的交是通过用左部与上部维的最大者和右部与下部维的最小者来计算的。如果任一个Rect是Empty,则返回Empty Rect。
两个矩形的并是通过用左部与上部维的最小值和右部与下部维的最大值来计算的。如果任一个Rect是Empty,则返回另一个Rect。
对于Offset方法,偏移只是被加到矩形的位置上。如果Rect为Empty则这个方法没有效果。
对于Inflate,膨胀量只是均等地应用于所有边。作出调整,包括:r.x=r.x-s.width;r.y=r.y-s.height;r.width=r.width+2*s.width和r.height=r.height+2*s.height。如果Rect为Empty,则这个方法没有效果,因为Empty Rect没有位置。
下面的标记句法指定x,y,宽度和高度。应当注意,这等价于System.Drawing.Rectangle的类型转换器所做的。
rectangle:
(coordinate comma-wsp){3}coordinate|″Empty″
2D计算的矩阵被表示为3x3矩阵。MIL使用行-向量句法。mil只允许仿射变换,并且因而只要求仅六个值,而不是完整的3x3矩阵。如下命名和定义这些。
m 11 m 12 0 m 21 m 22 0 offsetX offsetY 1
当矩阵乘以一个点时,它将该点从新的坐标系统变换到先前的坐标系统:
X newCoordSys y newCoordSys 1 &CenterDot; m 11 m 12 0 m 21 m 22 0 offsetX offsetY 1 = X oldCoordSys y oldCoordSys 1
变换可以嵌套到任何层。只要应用新的变换,它就与预乘它到当前变换矩阵相同:
X newCoordSys y newCoordSys 1 &CenterDot; m 11 2 m 12 2 0 m 21 2 m 22 2 0 offsetX 2 offsetY 2 1 &CenterDot; m 11 1 m 12 1 0 m 21 2 m 22 1 0 offsetX 1 offsetY 1 1
= X oldCoordSys y oldCoordSys 1
在API中大多数地方不直接用Matrix。代之以Transform类以深方式支持动画。
public struct System.Windows.Media.Matrix
{
//构建和设置
public Matrix();//默认为本体
public Matrix(
double m11,double m12,
double m21,double m22,
double offsetX,double offsetY);
//本体
public static Matrix Identity{get;}
public void SetIdentity();
public bool IsIdentity{get;}
//清除支持
public static Matrix Unset{get;}//所有值是NaN
public bool IsSet{get;}//如果任何NaN则false
//数学操作
public void Prepend(Matrix matrix);//“this”变成:matrix*this
public void Append(Matrix matrix)//“this”变成:this*matrix
//矩阵操作
public void Rotate(double angle);//追加旋转
public void RotatePrepend(double angle)//预挂旋转
public void Rotate(double angle,Point center);//追加旋转
public void RotateAtPrepend(double angle,Point center)//预挂旋转
public void Scale(Double scaleX,Double scaleY);//追加缩放
public void ScalePrepend(Double scaleX,Double scaleY);//预挂缩放
public void ScaleAt(Double scaleX,Double scaleY,Point point);//追加缩放
public void ScaleAtPrepend(Double scaleX,Double scaleY,Pointpoint);//预挂缩放
public void Skew(Double skewX,Double skewY);//追加偏斜,以度为单位
public void SkewPrepend(Double skewX,Double skewY);//预挂偏斜
public void Translate(Double offsetX,Double offsetY);//追加转换
public void TranslatePrepend(Double offsetX,Double offsetY);//预挂转换
  public static operator*(Matrix matrix1,Matrix matrix2);
 //变换服务
  public Point Transform(Point point);
  public void Transform(Point[]points);
  //由于这是一个向量忽略矩阵的偏移部分,
  public Vector Transform(Vector vector);
  public void TransformVectors(Vector[]vector);
  //求逆
  public double Determiant{get;}
  public bool HasInverse{get;}
  public Matrix Inverse{get;}//如果!HasInverse
   //则抛出ArgumentException InvalidOperationException
  //各成员
  public double M11{get;set;}
  public double M12{get;set;}
  public double M21{get;set;}
  public double M22{get;set;}
  public double OffsetX{get;set;}
  public double OffsetY{get;set;}
};
对于标记句法,顺序是M11,M12,M21,M22,OffsetX,OffsetY:
matrix:
 (coordinate comma-wsp){5}coordinate|″Identity″
三维视件和元素
本章节针对三维效果,主要通过供应用使用的媒体集成层提供直接的三维效果。这样的效果与远程、打印、桌面合成集成起来,并且清楚地参与MIL体系结构和元素模型及通过MIL的媒体合成性。例如,商业可视化对三维显示和交互有某些要求。这可能要求对成千上万对象的击中测试分辨率。并且将导致可能看来象在图41中所示的图像那样的交互可视化。
在此描述的特征通常针对运行时间呈现和交互,而不是通过建模工具提供的功能。以动画或运行时间构建情况为目标而提供的建模功能需要向运行时间揭示。例如,可提供3D文本突出,即使它实际上是一个建模特征,因为应用想要将文本数据绑定(databind),因而要求这为运行时间特征。
如上所述,在MIL系统中的Visual表示最后获得呈现的内容的2D合成树。注意,UiElement和Control是Visual。另外,Visual具有在该Visual自己的内容之前(以绘画者的算法术语)呈现的子Visual集合。如也在上面描述的,存在各种各样具体的Visual子类,包括RetainedVisual、SurfaceVisual、HwndVisual等等。RetainedVisual代表一组2D绘制指令,用户或者直接创建到该Visual上,或者作为接收来自布局系统的OnRender()回调的结果而这么做。
如将理解的,3D自然符合于2D视件世界。为此,提供Retained3DVisual,即像其2D对应视件,表示一列通过打开一绘制上下文并呈现到该绘制上下文中而被命令式地填充的绘制指令。这将有效地导致建立场景图或元数据或指令列到Visual本身中。
Retained3DVisual实质上是一组三维(呈现指令/场景图/元文件)数据,包括定义该场景的2D投影的灯光、照相机,用于映射投影的本地坐标空间中的矩形二维视见区,以及其它环境参数,诸如抗锯齿开关、雾开关等等。
注意,不为Retained3DVisual提供请求式OnRender()能力。2D有这个功能,以帮助管理在2D世界中绘制的数据量。象2D一样,呈现通过DrawingContext发生,其中“立即模式感觉”调用得到进行。例如,在2D中,在一绘制上下文中有下列代码:
DrawingContext ctx=...;
ctx.DrawRectangle(...);
ctx.PushTransform(...);
ctx.DrawGeometry(...);
ctx.PushTransform(...);
ctx.DrawEllipse(...);
ctx.Pop();
ctx.Pop();
为与2D一致,在3D中提供相似的模型如下:
DrawingContext3 ctx=...;
ctx.DrawMesh(mesh,material);
ctx.PushTransform(transform3);
etx.DrawMesh(...);
ctx.PushTransform(...);
ctx.DrawMesh(...);
ctx.Pop();
ctx.Pop();
注意,这个呈现模型对于保留模式3D视件(其中仅保存“指令”)和立即模式3D视件(其中呈现直接发生,并且需要在前面建立照相机)都工作良好。实际上,在保留模式情况下,内部所发生的是3D建模层次得到建立和保留。可替换地,在立即模式情况下,没有这样的事情发生,直接发出指令,并且保持一个上下文堆栈(用于变换,例如)。
下面是示出用3D视件API编程的例子。本例创建Retained3DVisual,获得要呈现的绘制上下文,向它呈现图元和灯光,设置照相机,并且将该视件加到控件的子视件:
//创建3D视件
Retained3DVisual visual3=new Retained3DVisual();
 //向它呈现
using(Drawing3DContext ctx=visua13.Models.RenderOpen())
{
 //呈现网格和灯光到几何图形中
 ctx.DrawMesh(mesh,material);
 ctx.PushTransform(transform3);
 ctx.DrawMesh(...);
 ctx.PushTransform(secondTransform);
 ctx.AddLight(...);
 ctx.DrawMesh(...);
 ctx.Pop();
 ctx.Pop();
}
//在视件上建立环境属性
visual3.Camera=new ProjectionCamera(...);
//将它添加到某个称为myControl的控件的合成子视件
((IVisualControl).AddChild(visual3);
2D集成到3D中是一个显著的特征,并且使很感兴趣的具有2D UI的情景能在3D世界中交互,能被映射到3D表面上等等。2D以不同的方法集成到3D中。一种方法是作为3D图元上的纹理。任何Avalon2D画刷(以及更复杂的材料描述)可以用于做3D的纹理。一种特殊的情况是不能作为任何视件(和因而控件,或整个应用UI)宿主的VisualBrush。提供分析击中测试以及进一步击中测试想要这么做的应用的该视件的机制,并且在某些情况下,将完成击中测试分析使得那些视件可以生存。注意,由于视件本身不是位图,视件-纹理化可以通过更复杂的技术来实现,诸如用视件中的2D几何图形并将它带进3D,因而具有3D向量图形而不是用作纹理的2D位图。
将2D集成到3D中的另一种方法是作为在3D上下文上的呈现指令。也希望能够仅呈现2D视件,屏幕对齐的和未缩放的,不具有任何透视效果,以特定的z深度,例如,以堆栈球体、2D视件和立方体,同时仍允许它们都共享同一z-缓冲器,因而允许例如一个球体通过一片2D UI。这将通过在Drawing3DContext上的“DrawVisual”指令来揭示。
如在此描述的,动画应当直观地运行,并且2D动画技术可直接传递给3D。一个例外是光栅化时间线。
上面示出将绘制指令发给上下文的用法的强制呈现风格。这不是说明用法,因而这种强制方法不适合于说明标记。
因为用上面的机制没有3D模型在外部显式地构建,(即使在内部它是),所以编程者不能寻址3D模型或者枚举其内容。结果,没有地方来写将模型作为输入并产生新模型的“效果”。
为提供建立和使用3D“资源”的说明方法,如在2D中用Brush、Pen、Geometry、Path等,提供许多类型以允许用户构建进入3D指令流的内容,并且所构建的对象可以被设置到Retained3DVisual中而代替使用上下文。
例如,上面基于Drawing3DContext的示例代码可以重写为:
//创建3D视件
Retained3DVisual visual3=new Retained3DVisual();
visual3.Models.Add(new MeshPrimitive3D(mesh,material);
Model3DCollection innerGroup1=new Model3DCollection();
innerGroup1.Transform=transform3;
innerGroup1.Add(new MeshPrimitive3D(mesh,material);
Model3DCollection innerGroup2=new Model3DCollection();
innerGroup2.Transform=secondTransform3;
innerGroup2.Add(new Light(...));
innerGroup2.Add(new MeshPrimitve3D(...));
innerGroup1.Add(innerGroup2);
visual3.Models.Add(innerGroup1);
//其它的一切与以前一样...
//在视件上建立环境属性
visual3.Camera=new ProjectionCamera(...);
//将它添加到某个称为myControl的控件的合成子视件
((IVisual)myControl).AddChild(visual3);
这里,正在建立一个模型,然后被赋给Retained3DVisual。PushTransform/Pop对由Model3DCollection的构造代替,后者本身具有变换和在它之下的Model。提供建模方法和基于强制上下文的方法两者,这为元素-层说明标记、视件枚举、场景图效果和视件内容的可修改性提供解决方案,并且以体系结构上可行的方法来完成。
建模类树的根是Model3D,它代表可以附着于Retained3DVisual的三维模型。最后,灯光、网格、.X文件流(因此它来自文件、资源、存储器等等)、模型分组和3D定位的2D视件都是模型。因而,存在下列层次:
·Model3D
 -- Model3DCollection-是Model3D的集合
 --  Primitive3D
  * MeshPrimitive3D(网格,材料,hitTestID)
  * ImportedPrimitive3D(流,hitTestID)(对于.x文件)
 -- Light
  * AmbientLight
  * SpecularLight
  * DirectionalLight
  * PointLight
   -- SpotLight
 -- VisualModel3D-具有Visual和Point3和HitTestID
Model3D类本身支持许多操作,包括取得3D边界框,取得和设置Model3D的Transform,取得和设置其它“节点”层属性如阴影和取得和设置hitTestObject。注意,在3D场景内没有揭示显式3D初始化的击中测试。换言之,没有将任意方向的光线投影到3D场景以查看击中什么的API。击中测试功能将通过执行对在Retained3DVisual中的2D投影的击中测试来访问。
并入3D引起在使2D坐标系统与3D坐标系统合理化时出现的难题。在2D中,坐标系统具有在左上部的原点,+x在右边,而+y在下边。
3D坐标系统可以是右旋的系统,其中+z出现在屏幕的外边,+x在右边(它与2D相同),而+y在上边(它与2D不同)。这是因为在3D图形上下文中的左旋坐标系统往往创建大量不必要的编程错误。注意,现代硬件具有下载每-顶点阴影器(per-vertex shader)的能力,因而使它有可能使用所希望的任何坐标系统约定。
坐标系统合理化的另一个方面是纹理所在的u,v空间。没有u,v空间的特定默认约定,但具有“+v下降”的模型将允许通过纹理化比具有“+v上升”的模型(对于那些模型,纹理将有可能显得颠倒)更直接映射2D UI。如果正在纹理化的模型没有适当确定方向的u,v网格,则在Material的Brush上的Transform属性可以用于抵消。
已经进行了许多实验来观察使文本在3D中显得吸引人的大多数可行的方法;(注意,这没有必要包含具有宽度、高度和深度的“3D文本”)。为此,一个应用可构建保持在3D中使用的文本(和其它任何2D元素)的2DVisual,确保该Visual得到过取样(例如,按4x-8x),并且随后使用这个Visual作为到平面或任何任意3D对象上的Material。如果得到的纹理化是非均质的,则结果是吸引人的文本。
注意,在本章节中描述的说明类型(例如,向量,点,灯光,网格,材料,图元,变换等等)都是能容易地通过基于XAML的标记使用标准的XAML CLR类类型描述机制来描述的。类型可具有TypeConverter,但如果没有,则它们能在标记中通过XAML提供的标准的简单和复杂属性描述机制来指定。注意,TypeConverter规范用于在纯基于串的类型表示出现在XAML中时解释它们。因而,例如,对于在ScaleTransform3D中使用的Vector3D,XAML标记如下:
<ScaleTransform3D scaleVector=″1,2,8″/>
注意,通过通用XAML分析器来分析和理解“ScaleTransform3D”和“scaleVector”,但将“1,2,8”提供给Vector3D的TypeConverter并且预期产生一个Vector3D(由于那是ScaleTransform3D的“ScaleVector”属性的类型)。而且,注意尽管没有显式地列出每个类型,但这些类型具有下列方法(这里示出的是Vector3D的方法,但可应用于其它对象):
public static bool operator=(Vector3D vector1,Vector3D vector2)
public static bool Equals(Vector3D vector1,Vector3D vector2)
public static bool operator!=(Vector3D vector1,Vector3D vector2)
public override bool Equals(objeet o)
public override int GetHashhCode()
public override string ToString()
而且,任何从Changeable(直接或间接地)派生的类型将必须在其上需要具有一个“public new MyType copy()”。这些图元类型仅在对在本章节中描述的其它类型的支持中存在。只要有可能,它们镜象反映2D中使用的图元类型,并且这种相似性是这些类型的设计目标。
Point3D对象是2D Point类型System.Windows.Point的直接模拟:
public struct System.Windows.Media3D.Point3D
{
 public Point3D();//初始化为0,0,0
 public Point3D(double x,double y,double z);
 public double X{get;set;}
 public double Y{get;set;}
 public double Z{get;set;}
 public void Offset(double dx,double dy,double dz);
 public static Point3D operator+(Point3D point,Vector3D vector);
 public static Point3D operator+(Point3D point,Vector3D vector);
 public static Point3D operator-(Point3D point,Vector3D vector);
 public static Vector3D operator-(Point3D point1,Point3Dpoint3D);
 public static Point3D operator*(Point3D point,Matrix3D matrix);
 public static Point3D operator*(Point3D point,Transform3Dtransform);
 public static explicit operator Vector3D(Point3D point);
 //3D点到4D点的显式提升。W座标变成1。
 public static explicit Point4D(Point3D point);
}
coordinate:
      double-number-representation
comma-wsp:
      one comma with any amount ofwhitespace before or after
coordinate-triple:
      (coordinate comma-wsp){2}coordinate
point3D:
      coordinate-triple
Vector3D是2D Vector类型System.Windows.Vector的直接模拟:
public struct System.Windows.Media3D.Vector3D
{
 public Vector3D();//初始化为0,0,0
 public Point3D(double x,double y,double z);
 public double X{get;set;}
 public double Y{get;set;}
 public double Z{get;set;}
 public double Length{get;}
 public double LengthSquared{get;}
 public void Normalize();//产生Vector3D单位长度
 public static Vector3D operator-(Vector3D vector);
 public static Vector3D operator+(Vector3D vector1,Vector3Dvector2);
 public static Vector3D operator-(Vector3D vector1,Vector3Dvector2);
 public static Point3D operator+(Vector3D vector,Point3D point);
 public static Point3D operator-(Vector3D vector,Point3D point);
 public static Vector3D operator*(Vector3D vector,double scalar);
 public static Vector3D operator*(double scalar,Vector3D vector);
 public static Vector3D operator/(Vector3D vector,double scalar);
 public static Vector3D operator*(Vector3D vector,Matrix3Dmatrix);
 public static Vector3D operator*(Vector3D vector,Transform3Dtransform);
 //返回点积:vector1.X*vector2.X+vector1.Y*vector2.Y
 public static double DotProduct(Vector3D vector1,Vector3Dvector2);
 //通过计算叉积返回两个输入向量之间的法向向量
 public static Vector3D CrossProduct(Vector3D vector1,Vector3Dvector2);
 //返回将v1旋转到v2所需的角度,以度为单位
 //这将返回(-180,180]度数之间的值
 public static double AngleBetween(Vector3D vector1,Vector3Dvector2);
 public static explicit operator Point3D(Vector3D vector);}
 //3D向量到4D点的显式提升。W座标变成0。
 public static explicit operator Point4D(Vector3D point);
point3D:
 coordinate-triple
Point4D添加第四个w组件到3D点,并且用于通过非仿射Matrix3D的变换。没有Vector4D,因为为1的‘w’组件转换成Point3D,并且为0的‘w’组件转换成Vector3D:
public struct System.Windows.Media.Point4D
{
  public Point4D();//初始化为0,0,0,0
  public Point4D(double x,double y,double z);
  public double X{get;set;}
  public double Y{get;set;}
  public double Z{get;set;}
  public double W{get;set;}
  public static Point4D operator-(Point4D point1,Point4D point2);
  public static Point4D operator+(Point4D point1,Point4D point2);
  public static Point4D operator*(double scalar,Point4D point);
  public static Point4D operator*(Point4D point,double scalar);
  public static Point4D operator*(Point4D point,Matrix3D matrix);
  public static Point4D operator*(Point4D point,Transform3D transform);
}
point4D:
 coordinate-quad
四元数显然是表示在三维中旋转的3D实体。它们的能力表现在能够在四元数之间内插(并因而动画)以实现平滑可靠的内插。特定的内插机制称为球面线性内插(Spherical Linear Interpolation)。
四元数或者可以从它们的分量(x,y,z,w)的直接描述来构建,或者作为轴/角度表示。第一表示可产生非标准化的四元数,对于它们某些操作没有意义(例如,抽取轴和角度)。
一旦构建Quaternion,则它的分量不能设置,因为在这么做时存在潜在的多义性,例如,设置在非标准化的Quaternion上的Angle没有意义。
public struct System.Windows.Media3D.Quaternion
{
 public Quaternion;//初始化为0,0,0,0
 //允许非标准化的四元数
 public Quaternion(double x,double y,double z,double w);
//允许通过轴和角度构建
public Quaternion(Vector3D axisOfRotation,double
  angleInDegrees);
//基本Quaternion分量
public double X{get;}
public double Y{get;}
public double Z{get;}
public double W{get;}
//轴/角度访问。如果没有标准化四元数则将引起异常。
public Vector3D Axis{get;}
public double Angle{get;}//以度为单位,就像其它的一切一样
//幅度为1?只有标准化的四元数可以在RotateTransform3D的中使用。
public bool IsNormalized{get;}
public Quaternion Conjugate();//返回四元数的共轭
public Quaternion Inverse();//返回四元数的逆
public Quaternion Normalize();//返回标准化的四元数
public static Quaternion operator+(Quaternion left,Quaternionright);
public static Quaternion operator-(Quaternion left,Quaternionright);
public static Quaternion operator*(Quaternion left,Quaternionright);
//平滑地在两个四元数之间内插
public static Quaternion Slerp(Quaternion left,Quaternion right,double t);
}
quaternion:
  coordinate-quad|//x,y,z,w表示
″(″coordinate-triple″)″coordinate//轴,角度表示
Matrix3D是System.Windows.Matrix的3D模拟。像Matrix一样,大多数API不用Matrix3D,而是用Transform3D,它以深方式支持动画。用3D计算的矩阵表示为4x4矩阵。MIL使用行-向量句法:
m 11 m 12 m 13 m 14 m 21 m 22 m 23 m 24 m 31 m 32 m 33 m 34 offsetX offsetY offsetZ m 44
当一个矩阵乘以一个点时,它将该点从新的坐标系统变换成先前的坐标系统。
变换可以嵌套至任何层。只要应用新的变换,则它与预乘它到当前的变换矩阵上是一样的:
 public struct System.Windows.Media3D.Matrix3D
{
//构建和设置
public Matrix();//默认为本体
public Matrix(
 double m11,double m12,double m13,double m14,
 double m21,double m22,double m23,double m24,
 double m31,double m32,double m33,double m34,
 double offsetX,double offsetY,double offsetZ,double m44);
//本体
 public static Matrix3D Identity;
 public void SetIdentity();
 public bool IsIdentity{get;}
 //数学操作
public void Prepend(Matrix3D matrix);//“this”变成:matrix*this
public void Append(Matrix3D matrix);//“this”变成:this*matrix
//旋转--四元数版本。如果想要轴/角度旋转,则建立来自轴/角度的四元数。
public void Rotate(Quaternion qaternion);
public Void RotatePrepend(Quaternion quaternion);
public void RotateAt(Quaternion qaternion,Point3D center);
public void RotateAtPrepend(Quaternion qaternion,Point3Dcenter);
public void Scale(Vector3D scalingVector);
public void ScalePrepend(Vector3D scalingVector);
public void ScaleAt(Vector3D scalingVector,Point3D point);
public void ScaleAtPrepend(Vector3D scalingVector,Point3Dpoint);
public void Skew(Vector3D skewVector);//追加偏斜,以度为单位
public void SkewPrepend(Vector3D skewVector);
public void SkewAt(Vector3D skewVector,Point3D point);
public void SkewAtPrepend(Vector3D skewVector,Point3D point);
public void Translate(Vector3D offset);//追加转换
public void TranslatePrepend(Vector3D offset);//预挂转换
public static Matrix3D operator*(Matrix3D matrix1,Matrix3Dmatrix2);
//变换服务。在Vector3D和Point3D上操作的那些引起异常,
//如果IsAffine==false。
public Point3D Transform(Point3D point);
public void Transform(Point3D[]points);
public Point4D Transform(Point4D point);
public void Transform(Point4D[]points);
//由于这是向量,忽略矩阵的偏移部分的
public Vector3D Transform(Vector3D vector);
public void Transform(Vector3D[]vectors);
//矩阵的特征
public bool IsAffine{get;}//如果m{1,2,3}4==0,m44==1则true。
public double Determinant{get;}
public bool HasInverse{get;}
public Matrix3D Inverse{get;}//如果!HasInverse则抛出
       InvalidOperationException
//各成员
public double M11{get;set;}
public double M12{get;set;}
public double M13{get;set;}
public double M14{get;set;}
public double M21{get;set;}
public double M22{get;set;}
public double M23{get;set;}
public double M24{get;set;}
public double M31{get;set;}
public double M32{get;set;}
public double M33{get;set;}
public double M34{get;set;}
public double OffsetX{get;set;}
public double OffsetY{get;set;}
public double OffsetZ{get;set;}
 public double M44{get;set;}
}
Transform3D,像2DTransform一样,是具有表示特定3D变换类型的具体子类的抽象基类。Transform3D的特定子类也是动画出现的地方。
在一个实现中,Transform3D的整个层次如下所述:
Transform3D
---- Transform3DCollection
--- AffineTransform3D
-------- TranslateTransform3D
-------- ScleTransform3D
-------- RotateTransform3D
---- MatrixTransform3D
根Transform3D具有构建特定Transform类的静态方法;(注意,它不揭示Matrix3D表示,因为这个Transform可以更宽泛):
 public abstract class System.Windows.Media.Media3D.Transform3D:Animatable
 {
   internal Transform3D();
   public new Transform3D Copy();
//创建公有变换的静态帮助者
  public static MatrixTransform3D CreateMatrixTransform(Matrix3D matrix);
  public static TranslateTransform3D CreateTranslation(Vector3D translation);
  public static RotateTransform3D CreateRotation(Vector3D axis,double angle);
  public static RotateTransform3D CreateRotation(Vector3D axis,double angle,
                               Point3D rotationCenter);
  public static RotateTransform3D CreateRotation(Quaternion quaternion);
  public static RotateTransform3D CreateRotation(Quaternion quaternion,
                              Point3D rotationCenter);
  public static ScaleTransform3D CreateScale(Vector3D scaleVector);
  public static ScaleTransform3D CreateScale(Vector3D scaleVector,
                            Point3D scaleCenter);
  public static Transform3D Identity{get;}
//实例成员
  public bool IsAffine{get;}
  public Point3D Transform(Point3D point);
  public Vector3D Transform(Vector3D vector);
  public Point4D Transform(Point4D point);
  public void Transform(Point3D[]points);
  public void Transform(Vector3D[]vectors);
  public void Transform(Point4D[]points);
}
注意,如果变换不是仿射的,则用Point3D/Vector3D的Transform()方法将引起异常。
Transform3DCollection将模仿TransformCollection,具有以修改上面的Create*方法相同方法修改的Add*方法:
public sealed class System.Windows.Media3D.Transform3DCollecton:
 Transform3D,IList
{
 //按照TransformCollection模型
}
AffineTransform3D是派生具体仿射3D变换的基类(转换,偏斜,旋转,缩放),并且它揭示对Matrix3D的读访问:
public abstract class
 System.Windows.Media3D.AffineTransform3D:Transform3D
{
 internal AffineTransform3D();//不可扩展
 public virtual Matrix3D Value{get;}
}
TranslateTransform3D:
public sealed class System. Windows.Media3D.TranslateTransform3D:
           AffineTransform3D
{
  public TranslateTransform3D();
  public TranslateTransform3D(Vector3D offset);
  public TranslateTransform3D(Vector3D offset,
                   Vector3DAnimationCollection offsetAnimations);
  public new TranslateTransform3D Copy();
  [Animations(“OffsetAnimations”)]
  public Vector3D Offset{get;set;}
  public Vector3DAnimationCollection OffsetAnimations{get;set;}
  public override Matrix3D Value{get;}
}
ScaleTransform3D:
 public sealed class System.Windows.Media3D.ScaleTransform3D:
        AffineTransform3D
{
 public ScaleTransform3D();
 public ScaleTransform3D(Vector3D scaleVector);
 public ScaleTransform3D(Vector3D scaleVector,Point3D scaleCenter);
  public ScaleTransform3D(Vector3D scaleVector,
                Vector3DAnimationCollection scalcVectorAnimations,
                Point3D scaleCenter,
                Point3DAnimationCollection scaleCenterAnimations);
  public new ScaleTransform3D Copy();
  [Animations(“ScaleVeetorAnimations”)]
  public Vector3D ScaleVector{get;set;}
  public Vector3DAnimationColleetion ScaleVectorAnimations{get;set;}
  [Animations(“ScaleCenterAnimations”)]
  pubic Point3D ScaleCenter{get;set;}
  public Point3DAnimationCoilection ScaleCenterAnimations{get;set;}
  public override Matrix3D Value{get;}
}
RotateTransform3D只是多了来自2D旋转的简单映射,因为旋转所围绕的轴的概念的引入(并且因而四元数的使用):
public sealed class RotateTransform3D:AffineTransform3D
{
 public RotateTransform3D();
 public RotateTransform3D(Vector3D axis,double angle);
 public RotateTransform3D(Vector3D axis,double angle,Point3Dcenter);
//提供给RotateTransform3D方法的四元数需要被标准化,否则将引起异常。
public RotateTransform3D(Quaternion quaternion);
public RotateTransform3D(Quaternion quaternion,Point3D center);
public RotateTransform3D(
 Quaternion quaternionl,
 QuaternionAnimationCollecton quaternionAnimations,
 Point3D center,
 Point3DAnimationCollection centerAnimations);
public new RotateTransform3D Copy();
//Angle//Axis只是在QuaternionRotation参数上的不同视图。
//如果Angle/Axis改变,QuaternionRotation将相应地改变,并且反之亦然。
 [Animations(″QuaternionAnimations″)]
 public Quaternion QuaternionRotation{get;set;}
 public QuaternionAnimatorCollection
        QuaternionRotationAnimations{get;set;}
 [Animations(″CenterAnimations″)]
 public Point3D Center{get;set;}
 public Point3DAnimatorCollection CenterAnimations{get;set;}
 public override Matrix3D Value{get;}
}
注意,这里只有Quaternion属性是可形成动画的。通常,轴/角度的动画往往不正常工作。使四元数动画化较好,并且可以从四元数的基值中提取轴和角度。如果想要简单地使角度绕固定轴形成动画,指定这个的容易的方法是建立两个表示那些位置的四元数,并且在它们之间形成动画。
MatrixTransform3D可直接从Matrix3D建立Transform3D:
 public sealed class System. Windows.Media3D.MtrixTransform3D:Transform3D
 {
   public MatrixTransform3D();
   public MatrixTranform3D(Matrix3D matrix);
   public new MatrixTransform3D Copy();
   public Matrix3D Value{get;set;}
  }
当在标记中指定Transform3D类型属性时,属性系统使用Transform类型转换器将串表示转换成适当的Transform派生对象。动画属性不使用这个句法描述,然而可以使用复杂的属性句法用于动画描述。
句法模仿2D Transform,其中“<>”表示可选的参数:
 · matrix(m00m01m02m11...m33)
 · translate(tx ty tz)
 · scale(sx<sy><sz><cx><cy><cz>)
  -- 果未指定<sy>或<sz>则假定为一致缩放
  -- 如果指定<cx><cy><cz>,则它们全部需要指定,<sx><sy>也要指定。它们用作缩放中心。如果未指定它们,则假定中心为0,0,0。
 · rotate(ax ay az angle<cx><cy><cz>)
  -- ax,ay,az指定旋转的轴
  -- angle是通过该轴的角度
  -- 如果未指定cx,cy,cz则假定为0,0,0。
下面是示例语法:
transform-list:
   wsp*transforms?wsp*
transforms:
   transform
   |transform comma-wsp+transforms
transform:
   matrix
   |translate
   |scale
   |route
   |skewX
   |skewY
 matrix:
  ″matrix″wsp*″(″wsp*
    number comma-wsp
    number comma-wsp
    ...13more times...
    number wsp*″)″
translate:
  ″translate″wsp*″(″wsp* number(comma-wsp number comma-wsp number)?
        wsp*″)″
scale:
  ″scale″wsp*″(″wsp* number(comma-wsp number comma-wsp number
        (eomma-wsp number comma-wsp number comma-wsp number)?
      )?wsp*″)″
rotate:
  ″rotate″wsp*″(″wsp* number wsp* nmber wsp* nmber wsp* number
     (comma-wsp number comma-wsp number comma-wsp number )?wsp* ″)″
Retained3DVisual从Visual派生,并且在这么做时得到其属性,包括Opacity、2D几何图形剪辑、2D混合模式、击中测试API、2D边界查询和参与Visual树。注意,不透明性、剪辑、混合模式和边界全部都应用于3D场景的2D投影。
public class
System.Windows.Media.Visuals.Retained3DVisual:Visual
{
public Retained3DVisual();
public Retained3DVisual(UIContext Context);
//面向模型的语义。默认值是空的Model3DCollection。
public Model3DCollection Models{get;set;}
//环境属性
//照相机--没有默认的,不提供照相机是错误的。
public Camera Camera{get;set;}
//ViewPort建立投影映射到2D中的地方。默认为0,0,1,1
[Animation(″ViewPortAnimations″)]
public Rect ViewPort{get;set;}
 public RectAnimationCollection ViewPortAnimations{get;set;}
 public Fog Fog{get;set;}
}
ViewPort框建立由Camera/Models确定的投影映射到2D本地坐标空间的地方。注意,没有在Retained3DVisual上的Bounds3D方法。这与Models.Bounds一样可用。
Drawing3DContext非常平行于2D DrawingContext,并且可从Retained3DVisual的Model3DCollection通过RenderOpen/RenderAppend访问。它类似立即模式呈现上下文,即使它在内部保留指令。
public class System.Windows.Media3D.Drawing3DContext:IDisposable
{
 internal Drawing3DContext();//不能公开地构建
 //呈现
 public void DrawMesh(Mesh3D mesh,Material material,objecthitTestToken);
 //这些是用于绘制象.x文件的导入图元
 public void DrawImportedPrimitive(ImportedPrimitiv3DSourceprimitiveSource,
  object hitTestToken);
 public void DrawImportedPrimitive(ImportedPrimitives3DSourceprimitiveSource,
  Material overridingMaterial,
  object hitTestToken);
 public void DrawVisual(Visual visual,Point3D centerPosition,
  object hitTestToken);
 public void DrawModel(Model3D model);
 public void AddLight(Light light);
 //堆栈操作
 public void PushTransform(Transform3D transform);
 public void Pop();
 public void Close();//也由Dispose()调用;
}
上面参考建模API描述在这些Drawing3DContext操作的语义上的特定细节,对于建模API,Drawing3DContext是方便的。例如,DrawImportedPrimitive(ImportedPrimitive3DSourceprimitiveSource,objectTestToken)建立ImportedPrimitive3D,并且将它添加到当前累积的Model3D(它进而由上下文上的Push/Pop方法来操作)中。
DrawModel()是在“上下文”世界和“建模”世界之间的另一个交叉点,允许Model3D被“绘制”到上下文中。没有来自Drawing3DContext的显式“读回(callback)”,因为它具有Model3DCollection在其背后,并且在必要时可以枚举该集合。
建模API是这些类的公开和受保护的API,(未示出继承的成员),其中Model3D是从其建立的一切的抽象类:
public abstract class Model3D:Animatable
{
 public Transform3D Transform{get;set;}//默认为本体
 public ShadingMode ShadingMode{get;set;}
 public object HitTestToken{get;set;}
 public Rect3D Bounds3D{get;}//这个模型的边界
 //唯一的“空”模型。
 public static Model3D EmptyModel3D{get;}
}
Model3Collection是构建的模型的组合,并且视为一个单元,可选地将其它属性变换或应用于它们:
public sealed class Model3DCollecton:Model3D,IList
{
 public Model3DCollection(params Model3D[]models);
 public Model3DCollection(ICollection collection);
 //Drawing3DContext语义
 public Drawing3DContext RenderOpen();
 public Drawing3DCont ext RenderAppend();
//IList接口(这里没有全部列出...)
 public int Add(Model3D model);
 public Model3D this[int index]{get;set;}
 public void Insert(..);
 //等等...
}
注意,Model3DCollection还具有RenderOpen/Append,它返回Drawing3DContext。这个上下文的使用修改ModelCollection本身。在RenderOpen()和RenderAppend()之间的差异是RenderOpen()首先清除集合。而且要注意,在这个实现中,一次只有一个Drawing3DContext可在Model3DCollection上打开,并且当它被打开时,应用不可直接访问(读或写)该Model3DCollection的内容。
灯光是Model3D。这些包括Ambient、Positional、Directional和Spot灯光。灯光具有作为建模层次一部分的附加属性,并且因而属于坐标空间变换。所提供的是在灯光上环境的、漫射的和反射的颜色。还要注意,没有分层地限定范围的灯光或者以特定量为范围的灯光。如下阐述适当的灯光层次:
Model3D
---- Light(抽象的)
------- AmbientLight(具体的)
------- DirectionalLight(具体的)
------- PointLight(具体的)
----------- SpotLight(具体的)
基灯光类是抽象类:
public abstract class Light:Model3D
{
internal Light();//只允许公开构建--没有第3方灯光
[AniAmation(“AmbientColorAnimations”)]
public Color AmbientColor{get;set;}
public ColorAnimationCollection AmbientColorAnimations{get;set;}
[Animation(“DiffuseColorAnimationis”)]
public Color DiffuseColor{get;set;}
public ColorAnimationCollection DiffuseColorAnimations{get;set;}
[Animation(“SpecularColorAnimations”)]
public Color SpecularColor{get;set;}
public ColorAnimationCollection SpecularColorAnimations{get;set;}
}
环境灯光不均匀地照亮对象,无论它们的形状:
public sealed class AmbientLight:Light
{
  public AmbientLight(Color ambientColor);
}
定向灯光没有空间中的位置并且沿特定的方向投影其灯光,该方向由定义它的向量指定:
 public sealed class DirectionalLight:Light
 {
   public DirectionalLight(Color diffuseColor,Vector3D direction);//common usage
 [Animation(“DirectionAnimations”)]
 public Vector3D Direction{get;set;}
 public Vector3D AnimationCollection DirectionAnimations{get;set;}
}
方向不必标准化,但它必须具有非零的量值。
定位灯光具有空间中的位置并且以所有方向投影其灯光。灯光的衰退由衰减和范围属性控制:
[强名字继承要求因此第3方不能派生...不能封,
因为SpotLight从它派生...]
public class PointLight:Light
{
public PointLight(Color diffuseColor,Point3D position);//公共用法
[Animation(″PositionAnimations″)]
public Point3D Position{get;set;}
public Point3DAnimationCollection PositionAnimations{get;set;}
//灯光的范围,在它之外没有效果。在本地坐标中指定它。
[Animation(″RangeAnimations″)]
public Point3D Range{get;set;}
public DoubleAnimationCollection RangeAnimations{get;set;}
//不变的线性的和二次的衰减系数定义
//灯光如何在其位置与Range值之间衰减。
[Animation(″ConstantAttenuationAnimations″)]
public Point3D ConstantAttenuation{get;set;}
public DoubleAnimationCollection ConstantAttenuationAnimations{get;set;}
[Animation(″LinearAttenuationAnimations″)]
 public Point3D LinearAttenuation{get;set;}
 public DoubleAnimationCollection LinearAttenuationAnimations{get;set;}
 [Animation(″QuadraticAttenuationAnimations″)]
 public Point3D QuadraticAttenuation{get;set;}
 public DoubleAnimationCollection QuadraticAttenuationAnimations{get;set;}
}
注意,PointLight必须在其上具有强名字继承;以使SpotLine从它派生,但第三方不行。
SpotLight从PointLigh派生,因为它具有位置、范围和衰减,但还增加方向和控制灯光“锥体”的参数。为了控制“锥体”,必须指定outerConeAngle(在其外没有东西被照亮)和innerConeAngle(在其内的一切都被完全照亮)。在内部锥体之外与外部锥体之间的灯光线性地衰减。(注意,在内部锥体与外部锥体之间存在“角形”衰退,并且在相对于灯光的位置的距离上衰退,并且受衰减和范围的影响。)
   public sealed class SpotLight:PointLight
   {
     public SpotLight(Color color,
               Point3D position,
               Vector3D direction,
               double outerConeAngle,
               double innerConeAngle);
  [Animation(“DirectioAnimations”)]
  public Vector3D Direction{get;set;}
  public Vector3DAnimationCollection DirectionAnimations{get;set;}
  [Animation(“OuterConeAngleAnimations”)]
  public double OuterConeAngle{get;set;}
  public DoubleAnimationCollection OuterConeAngleAnimations{get;set;}
  [Animation(“InnerConeAngleAnimations”)]
  public double InnerConeAngle{get;set;}
  public DoubleAnimationCollection InnerConeAngleAnimations{get;set;}
}
注意,像MIL API中所有地方一样,以度为单位指定角度。
Primitive3D是导致在树中呈现的叶节点。具体类引入显式指定的网格,以及导入图元(.x文件)。构造函数是内部的;(可扩展性通过MeshPrimitive3D是可行的)。
public abstract class Primitive3D:Model3D
{
 internal Primitive3D(object hitTestToken);
}
MeshPrimitive3D用于用网格和材料建模:
public sealed class MeshPrimitive3D:Primitive3D
{
  public MeshPrimitive3D(Mesh3D mesh,Material material,object hitTestToken);
  public Mesh3D Mesh{get;set;}
  public Material Material{get;set;}
}
注意,MeshPrimitive3D是叶几何图形,并且它包含Mesh而非其本身。这意味着Mesh可以在多个MeshPrimitive3D之间共享,这些对象具有不同的材料,属于不同的击中测试,在不复制网络数据的情况下。
ImportedPrimitive3D表示外部获得的图元(有可能用材料和动画),被引入或转换成适当的内部形式。它被视为刚性模型。它的描述例子是.X文件,并且存在显式导入XFile的ImportedPrimitive3DSource子类。
public sealed class ImportedPrimitive3D:Primitive3D
{
 public ImportedPrimitive3D(ImportedPrimitive3DSource primitive,
  object hitTestToken)
 public ImportedPrimitive3DSource PrimitiveSource{get;set;}
 //如果存在的话,允许覆盖导入的材料。
 //如果未指定,则这是null,并且使用内建材料。
 public Material OverridingMaterial{get;set;}
}
由于预期.x文件公共地包括在场景中,因此支持用于表达这个的简单TypeConverter格式,诸如:
<ImportedPrimitive3D xfile=″myFile.x″/>
VisualModel3D用任何Visual(2D,按定义),并且将它放在场景中。当被呈现时,它是屏幕对齐的,并且它尺寸不受影响,但它处在从照相机起的特定z-平面。该Visual将保持交互。
public sealed class VisualModel3D:Model3D
{
  public VisualModel3D(Visual visual,Point3 centerPoint,object hitTestToken);
  public Visual Visual{get;set;}
  public Point3D CenterPoint{get;set;}
}
呈现VisualModel3D首先将CenterPoint变换成世界坐标。然后它将Visual以屏幕对齐方式呈现到像素缓冲器中,其中z为放置视件中心的变换的CenterPoint。在照相机运动下,VisualModel3D占据相同数量的屏幕不动产,并且向前面向而不受灯光影响,等等。在这个视件的照相机相对于场景的其余部分运动期间固定点将是视件的中心,由于放置基于该点发生。
提供的Visual是完全交互的,并且实际上以包围它的Retained3DVisual“作为父亲”,这意味着给定的Visual只能在任何VisualModel3D中使用一次,就像Visual只能具有单个父亲。注意,这是两种用于将交互视件嵌入3D的机制之一。另一个是使用VisualMaterial和在图元上使用它。
DrawMesh和DrawVisual两者都用hitTestToken“对象”。这将由IVisual.HitTest()在3D Visual得到击中时返回。然后使用它来消除在3D中获得击中对象的歧义。注意“拾取路径”在此不需要,因为各DrawMesh,即使它取得相同的网格,也可以给它提供不同的“hitTestToken”。
在一个实现中,HitTesting是通过Direct3D RayIntersect实用程序实现的,后者提供击中的距离,击中点的u,v坐标,允许在最初击中对象之外的击中测试,等等。还要注意,击中测试结果具有足够的信息来给出被击中的图元的u,v坐标,以允许转换成关于覆盖它的任何纹理的击中测试查询。而且,对于VisualModel3D,以及VisualMaterial的使用,击中测试将在正确的映射点进入到2D视件中。这个结果通过允许来自外部2D环境的击中测试上下文出现,继续通过3D环境,并且在嵌套的2D环境中再次拾取,有可能永远下去。它的最终结果是在提供这个通过(pass-through)、用户交互到活动的、纹理映射的Avalon2D控件中时正确地操作。
本发明支持从外部源导入3D图元的一般概念。在v1中它的一个实现是来自.x文件格式。
pubilc abstract sealed class ImportedPrimitive3DSource
{
 //不允许外部派生
 internal ImportedPrimitive3DSource();
}
.X文件作为XFile3DSource出现在系统中,并且用于构建ImportedPrimitive3D。将它分出独立的数据类型,因此它可以在多个ImportedPrimitive3D中使用和共享。.x文件的适当转换和处理可在构建它时发生,或者可以延迟。注意,.x文件被导入为单元,并且在它内部没有可单独寻址的内容。
public sealed class XFile3DSource:ImportedPrimitive3DSource
{
 //.X文件数据指定为流,允许它来自任意源(文件,资源,存储器,URL)
 public XFile3DSource(IStream xFileStream);
}
Mesh3D图元是直接的三角形图元(允许索引的或非索引两者的描述),它可以以编程方式构建。注意,这支持预期是图元的最普通用法的内容(即位置,标准(normal),颜色和纹理信息,其中最后三个是可选的)。网格也允许选择要将它显示为三角形、直线还是点。它还支持三个用于解释索引的拓扑,即三角形列表,三角形带,和三角形扇。
对于Mesh3D不直接支持的顶点格式和其它图元构建,可以构建和导入.x文件。
public sealed class System.Windows.Media3D.Mesh3D:Animatable
{
 public Mesh3D();
 //顶点数据。Normals,Colors和TextureCoordinates都是可选的。
 public Point3DCollection Positions{get;set;}
 public Vector3DCollection Normals{get;set;}//假定要标准化
 public ColorCollection Colors{get;set;}
 public ColorCollection SpecularColors{get;set;}
 public PointCollection TextureCoordinates{get;set;}
 //Topology数据。如果为null,则视为非索引的图元
 public IntegerCollection TriangleIndices{get;set;}
 //图元类型--默认=TriangleList
 public MeshPrimitiveType MeshPrimitiveType{get;set;}
}
MeshPrimitiveType定义为:
   public enum System.Windows.Media3D.MeshPrimitiveType
   {
     TriangleList,
     TriangleStrip,
     TriangleFan,
     LineList,
     LineStrip,
     PointList
   }
在Mesh3D中的每-顶点数据被分成Positions,Normals,Colors和TextureCoordinates。在这些之中,只有Positions是要求的。如果提供任何其它数据,则它们必须具有与Positions集合精确相同的长度,否则将引起异常。
Normals,如果提供,则假定被标准化。注意,系统将不试图基于拓扑/近似来计算标准(normal);代之以当想要标准时,必须提供它们。
TriangleIndices集合具有索引顶点数据以确定组成网格的三角形的每-顶点信息的成员。这个集合基于MeshPrimitiveType的设置来解释。对于TriangeList,在TriangleIndices集合中的每三个元素定义一个新的三角形。对于TriangleFan,索引0,l,2确定第一个三角形,然后每个后续的索引i确定由顶点0,i,i-l给出的新三角形。对于TriangleStrip,索引0,1,2确定第一个三角形,并且每个后续的索引i确定由顶点i-2,i-1和i给出的新三角形。LineList,LineStrip和PointList具有相似的解释,但按照直线和点而不是三角形来呈现。
如果TriangleIndices为null,则Mesh被实现为非索引的图元,它等价于保存长度为n的Positions集合的值0,1,...,2,n-1的TriangleIndices。
在构建Mesh时,该实现创建可选的D3D结构表示这个网格。这里,实际的Collection数据结构可以由Mesh实现抛弃以避免数据的重复。如果通过某些其它机制访问则网格的后续读回(例如遍历Retained3DVisual模型层次)将有可能重新从所保持的D3D信息重新构建数据,而不是保留原数据。
网格从Changeable派生(通过Animatable),并且因而可以被修改。该实现将捕捉对顶点和索引数据的设置,并且将那些改变传送给D3D数据结构。对在网格中的顶点或索引数据的说明动画没有显式的支持。换言之,例如,这里看不到Point3DAnimationCollections。这与2D折线路径一致,例如。
像其它类型一样,XAML复杂属性句法可以用于指定定义Mesh3D的集合。然而,那是笨拙而冗长的,并且因而提供TypeConverter来使指定更简洁。
在网格中定义的每个集合可以用要被分析并用于创建集合的单个数字串。例如,表示一个只具有位置和颜色的索引的三角形带的Mesh如下指定:
<Mesh3D
 meshPrimitiveType=“TriangleStrip”
 positions=“1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18”
 colors=“red blue green cyan magenta yellow”
 triangleIndices=“1,3,4,1,2,3,4,5,6,1,2,4,2”
 />
当然,这些中的任何一个都可用复杂的属性句法来冗长得多地表示。
构建Primitive3D的方法用定义其外观的Material。Material是抽象基类,具有三个具体子类:BrushMaterial,VisualMaterial和AdvancedMaterial。BrushMaterial和VisualMaterial都是另一个称为BasicMaterial抽象类的子类。因而:
Material
---- BasicMaterial
-------- BrushMaterial
-------- VisualMaterial
---AdvancedMaterial
BrushMaterial方法用单一Brush并且可以用于大范围的效果,包括实现透明性(或者每-像素或标量),具有纹理变换(甚至是动画的),使用视频纹理,隐含自动生成的mipmap等等。明确地说,对于纹理纯色,图像、渐变或甚至另一个Visual、SolidColorBrush、ImageBrush、GradientBrush或VisualBrush可用于创建BrushMaterial。
VisualMaterial方法设计为从Visual构建材料。这个材料将是交互的,在输入将被传递到来自将其嵌入的3D世界的视件的意义上。在这个与具有VisualBrush的BrushMaterial之间的一个差别是BrushMaterial是非交互的。
AdvancedMaterial类,尽管认为比简单地使用BrushMaterial或VisualMaterial更复杂,但提供进一步的灵活性。
public abstract class Material:Animatable
{
 internal Material();//不允许外部子类
 public new Material Copy();//遮蔽Changeable.Copy()
 public static Material Empty{get;}//唯一的材料
}
 public abstract class BasicMaterial:Material
{
 internal BasicMaterial();//不允许外部子类
 public new BasicMaterial Copy();//遮蔽Changeable.Copy()
}
Material通过基于Brush而获得灵活性和“概念的节约”。例如,不需要有反射像象视频纹理、渐变纹理等内容的单独的Texture结构,因为那些都可以指定为Brush。Brush已经封装了alpha-掩模和标量不透明性值两者,因此那些都变成可用于纹理。Brush已经具有与其相关联的2D Transform,在纹理化的情况下,将解释为用于变换网格中的变换uv坐标以映射到纹理的纹理变换。Brush是挂起原料过程着色器如木材纹理着色器的正确的地方。这随后在2D中用作填充或笔,而在3D用作纹理。没有特定的API支持需要在过程着色器的3D空间中给出。
注意,像素或顶点着色器可提供为“原料(stock)”着色器,其中许多将被参数化。这些在API中可访问的方法用于在2D世界中有意义的着色器,它们作为Brush的具体子类被揭示,其中它们的参数化或者通过在类上的构造函数来表达,或者作为在类上的属性。它们随后可以应用于2D对象。只在3D中有意义的着色器将作为Material的具体子类(可能作为BasicMaterial的子类),其中它们也可以通过它们的构造函数来参数化。这个揭示随后将允许着色器能被应用于3D(以及如果适当2D)网格。
如上所述,BrushMaterial封装Brush。应用于Primitive3D的BrushMaterial视为纹理。纹理被直接映射--即,在被映射的图元上的2D u,v坐标将直接索引到在由纹理变换修改的Texture上相应的x,y坐标。注意,像其它2D一样,纹理的坐标系统从左上(0,0)出发,正y向下。
用于Brush的VisualBrush不接受输入,但它依照在其上的任何动画或者任何对它发生的结构改变来更新。为使用Visual作为Material并且仍接收输入,使用VisualMaterial,如在此所述的。
public sealed class BrushMaterial:BasicMaterial
{
 public BrushMaterial Copy();//遮蔽Material.Copy()
 public Brush Brush{get;set;}
 //附加的纹理化专用旋钮。
}
如上所述,VisaulMaterial封装交互式Visual。这与由Visual使用的BrushMaterial不同,因为该Visual以其纹理化形式保持活动。注意,由于映射基于与图元相关联的u,v栅格,因此存在用户-输入没有其2D对应对象的完全保真度的情况。例如,考虑一个鼠标-捕捉情景,其中2D控件捕捉鼠标(例如用于实现滚动条行为)。在这些情景下,鼠标被允许偏离滚动条,但系统能够计算出,例如,鼠标相对于滚动条所在的y位置,并正确地操作。在控件被纹理化到具有u,v栅格的图元上并且鼠标偏离该图元的情况下,则通常没有办法作出这个决定。有某些事情不能做,虽然编辑成抵消这个,但通常,这变成映射到2D空间上的限制。注意,该Visual然后实际上以某种方式将根Retained3DVisual作为父亲。在一个实现中,在多于一个Material中使用单一UiElement,或者在多于一处使用VisualMaterial是非法的,因为事实上框架基于控件的单一父亲。
public sealed class VisualMaterial:BasicMaterial
{
 public VisualMaterial(Visual visual);
 public new VisualMaterial Copy();//遮蔽Changeable.copy()
 public Visual Visual{get;set;}
 --(需要添加viewport/viewbox材料用于定位...)
 //附加的纹理化专用旋钮。
}
BrushMaterial/VisualMateriai和BumpMap用于定义AdvancedMaterial:
public class AdvancedMaterial:Material
{
 public AdvancedMateriai();
 //添加公共构造函数。
 public new AdvancedMaterial Copy();//遮蔽Changeable.Copy()
 public BasicMaterial DiffuseTexture{get;set;}
 public BasicMaterial SpecularTexture{get;set;}
 public BasicMaterial AmbientTexture{get;set;}
 public BasicMaterial EmissiveTexture{get;set;}
 [Animations(″SpecularPowerAnimations″)]
 public double SpecularPower{get;set;}
 public DoubleAnimationCollection SpecularPowerAnimations{get;set;}
 public BumpMap DisffuseBumpMap{get;set;}
 public BumpMap ReflectionBumpMap{get;set;}
 public BumpMap RefractionBumpMap{get;set;}
 public BrushMaterial ReflectionEnvironmentMap{get;set;}
 public BrushMaterial RefractionEnvironmentMap{get;set;}
}
注意,EnvironmentMap是预期用特定的格式来支持立方体-映射的纹理。明确地说,立方体映射的六个面必须在与Texture相关联的Brush的部分中表示(有可能象在Brush上的3x2栅格一样的东西)。注意,Ambient、Diffuse和Specular属性用BasicMaterial,而不是一般的Material,因为它们不允许被指定为AdvancedMaterial本身。而且,注意环境映射只有BrushMaterial,因为VisualMaterial提供的交互性对于环境映射没有意义。
凹凸映射是像纹理一样通过在图元上的纹理坐标获得映射到3D图元的栅格。然而,内插的数据解释为对表面标准(normal)的扰动,导致图元“崎岖不平”的外观。为实现这个,凹凸映射传送诸如标准(normal)扰动之类的信息及潜在地其它信息。它们不传送颜色或透明度信息。由此,不适合使用Brush作为凹凸映射。因此,可提供新的BumpMap类,作为特定像素格式的ImageSource。
Material提供简单的TypeConverter,它允许Brush的串描述自动地提升到BrushMaterial中:
Material:
 ...委托给Brush类型转换器...
这允许如下的描述:
<MeshPrimitive3D...Material=″yellow″/>
<MeshPrimitive3D...Material=″LinearGradient blue green″/>
<MeshPrimitive3D...Material=″HorizontalGradi ent orange purple″/>
<MeshPrimitive3D...Material=″*Resource(myImageResource)″/>
还有复合属性符号,
<MeshPrimitive3D>
<MeshPrimitive3D.Material>
 <LinearGradientBrush>
   ...........
可提供模型的Ambient参数,它在几何图形层次中在任意层处是不可嵌入的。例如,可以通过在Retained3DVisual上设置Fog属性将雾添加到场景,例如,可用的Fog是“像素雾”。Fog表示为抽象类,并且层次如下所示:
public abstract class Fog:Animatable
{
 //仅在内部可构建
 internal Fog(Color color);
  public new Fog Copy();//隐藏Changeable.Copy()
  [Animation(″ColorAnimations″)]
  public Color Color{get;set;}
  public ColorAnimationCollection ColorAnimations{get;set;}
  //″没有雾″的唯一表示
  public static Fog NoFog{get;}
 }
public sealed class LinearFog:Fog
{
  public LinearFog(Color color,double fogStart,double fogEnd);
  [Animation(“FogStartAnimations”)]
  public double Fogstart{get;set;}
  public DoubleAnimationCollection FogStartAnimations{get;set;}
  [Animation(“FogEndAnimations”)]
  public double FogEnd{get;set;}
  public DoubleAnimationCollection FogEndAnimations{get;set;}
}
public sealed class ExponentialFog:Fog
{
  public ExponentialFog(Color color,double fogDensity,bool squaredExponent);
  [Animation(“FogDensityAnimations”)]
  public double FogDensity{get;set;}
  public DoubleAnimationCollection FogDensityAnimations{get;set;}
  public bool SquaredExponent{get;set;}
}
fogDensity范围为0-1,并且是雾密度的标准化表示。fogStart和fogEnd包括在设备空间[0,1]中指定的z-深度并且表示雾开始和结束的位置。
Camera是一个机制,通过它3D模型被投影到2D视件上。Camera本身是抽象类,具有两个具体子类--ProjectionCamera和MatrixCamera。ProjectCamera用易于理解的参数如Position、LookAtPoint和FieldOfView来构建Camera。MatrixCamera采用用于定义世界-到-设备(World-ToDevice)变换的Matrix3D。
public abstract class Camera:Animatable
{
 //仅允许在内部建立
 internal Camera();
 public new Camera Copy();//隐藏Changeable.Copy()
}
在Retained3DVisual中,Camera用于提供视图到Model3D上,并且所得到的投影被映射到建立在Retained3DVisual上的2D ViewPort中。注意,Retained3DVisual的2D边界框简单地是3D模型的投影3D框,由其凸起的、轴对齐的壳体覆盖,被剪辑成在视件上建立的剪辑。
ProjectionCamera是用于由诸如Position、LookAtPoint和FieldOfView之类参数构建照相机的工具。它封装两个透视投影和正交投影。图42提供ProjectionCamera有关方面的良好表示,示出检视(viewing)和位置,(其中FieldOfView应当在水平方向)。
public class ProjectionCamera:Camera
{
 //公共构造函数
 public ProjectionCamera();
 public ProjectionCamera(Point3D position,
  Vector3D lookDirection,
  Vector3D Up,
  double fieldOfView);
 public new ProjectionCamera Copy();//隐藏Changeable.copy()
//Camera数据
public bool IsOrthographic{get;set;}//默认==false:Perspective
[Animation(″NearPlaneDistanceAnimations″)]
public double NearPlaneDistance{get;set;}//默认=0
public DoubleAnimationCollection NearPlaneDistanceAnimations{get;set;}
[Animations(″FarPlaneDistanceAnimations″)]
public double FarPlaneDistance{get;set;}//默认=无穷远
public DoubleAnimationCollection FarPlaneDistanceAnimations{get;set;}
public double NearPlaneDistance{get;set;}//default=0
public DoubleAnimationCollection NearPlaneDistanceAnimations{get;set;}
[Animations(“FarPlaneDistanceAnimations”)]
public double FarPlaneDistance{get;set;}//default=infinity
public DoubleAnimationCollection FarPlaneDistanceAnimations{get;set;}
[Animations(“FieldOfViewAnimations”)]
public double FieldOfView{get;set;}
public DoubleAnimationCollection FieldOfViewAnimations{get;set;}
[Animations(“PositionAnimations”)]
public Point3D Position{get;set;}
public Point3DAnimationCollection PositionAnimations{get;set;}
[Animations(“LookDirectionAnimations”)]
public Vector3D LookDirection{get;set;}
public Vector3DAnimationCollection LookDirectionAnimations{get;set;}
  [Animations(“UpAnimations”)]
  pubic Vector3D Up{get;set;}
  public Vector3DAnimationCollection UpAnimations{get;set;}
}
注意,FieldOfView表示水平视野,并且以度数单位指定(像其它MIL角度)。Near和Far PlaneDistance代表从照相机的Position起沿LookDirection向量的3D世界-坐标距离。NearPlaneDistance默认为零并且FarPlaneDistance默认为无穷远。
在实际投影时,如果NearPlaneDistance和FarPlaneDistance分别仍是零和无穷远,则检查模型并且依照照相机投影来投影它的边界量(boundingvolume)。然后检查得到的边界量,因此将近平面距离设置为边界量的垂直于最接近照相机位置的LookDirection的平面。这实际上与远平面相同,但使用最远的平面。这导致z-缓冲器分辨率的最优使用,同时仍显示整个模型。如果IsOrthographic为true,则使用正交投影,并且忽略FieldOfView。
注意,由ProjectionCamera的参数定义的“投影平面”被映射到在Retained3DVisual上的ViewPort矩形。
Camera的MatrixCamera子类提供直接指定Matrix为投影变换的工具。这对于具有它们自己的矩阵计算机制的应用是有用的。
public class MatrixCamera:Camera
{
 //公共构造函数
 public MatrixCamera();
 public MatrixCamera(Matrix3D matrix);
 public new MatrixCamera Copy();//隐藏Changeable.Copy()
 //Camera数据
 public Matrix3D Matrix{get;set;}//默认=本体
}
注意,MinimumZ和MaximumZ值直接控制z-缓冲器范围。在应用Matrix作为投影矩阵之后考虑它们。
结果的投影被映射到Retained3DVisual上的ViewPort矩形,并且表示最终从3-空间到2-空间的转变。
下面是用XAML的更完整的标记,示出整个Model3D层次的描述。注意,有些句法可改变。
下面的例子简单地创建一个Model,它具有两个导入的.x文件和在它们之一上的旋转变换(围绕z-轴45度),以及位于0,1,0处之上的单一白色点灯光。
<Model3DCollection>
 <!--模型子对象用作这里的子对象--/>
 <PointLight position=″0,1,0″diffuseColor=″white″/>
 <ImportedPrimitive3D xfile=″myFile.x″/>
 <Model3DCollection transform=″rotate(0,0,1,45),scale(2)″>
  <ImportedPrimitive3D xfile=″mySecondFile.x″/>
 </Model3DCollection>
</Model3DCollection>
这个标记可以在文件、流、资源或任何合适的实体中。客户机程序将调用该XAML的加载,并且将进而构建由如所希望的应用使用的完整Model3DCollection。
下面的例子提供显式说明的MeshPrimitive3D,通过使用复杂-属性XAML句法。该网格将用从黄色到红色的LinearGradient来纹理化。在场景中还有一个灯光。
<Model3DCollection>
 <!--模型子对象用作这里的子对象--/>
 <PointLight position=″0,1,0″diffuseColor=″white″/>
<MeshPrimitive3D material=″LinearGradient yellow red″>
 <MeshPrimitive3D.Mesh>
  <Mesh3D
    meshPrimitiveType=″TriangleStrip″
    positions=″1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18″
    normals=″...可感知的标准向量...″
    textureCoordinates=.5,.5,1,1,0,0,.25,.25,.3,.4,.7,.8″
    triangleIndices=″1,3,4,l,2,3,4,5,6,1,2,4,2″/>
  </MeshPrimitive3D.Mesh>
 </MeshPrimitive3D>
</Model3DCollection>
该例子用第一个.x文件并且添加XAML指定的动画。这个特定的例子添加均匀缩放,它通过5秒将.x文件从1x缩放到2.5x,倒转,并无限地重复。它还使用加速/减速来缓进/缓出其缩放:
<Model3DCollection>
<!--模型对象用作这里的子对象--/>
 <PointLight position=”0,1,0””diffuseColor=”=white”/>
<ImportedPrimitive3D xfile=”myFile.x”>
 <ImportedPrimitive3D.Transform>
  <ScaleTransform3D>
   <ScaleTransform3D.ScaleVector>
    <VectorAnimation
      from=”1,1,1”
      to=”2.5,2.5,2.5”
      begin=”immediately”
      duration=”5”
      autoReverse=”true”
      repeatDuration=”indefinite”
      acceleration=”0.1”
           deceleration=”0.1”/>
     </ScaleTransform3D.ScaleVector>
    <ScaleTransform3D>
   </ImportedPrimitive3D.Transform>
  </ImportedPrimutive3D>
</Model3DCollection>
这个例子导入一个.x文件并且应用一个活动UI作为其材料:
<Model3DCollection>
 <!--模型子对象用作这里的子对象--/>
 <PointLight position=″0,1,0″diffuseColor=″white″/>
 <ImportedPrimitive3D xfile=″myFile.x″>
  <ImportedPrimitive3D.OverridingMaterial>
   <VisualMaterial>
    <Button Text=″Press Me″OnClick=″button OnClick″/>
   </VisualMaterial>
  </ImportedPrimive3D.OverridingMaterial>
 </ImportedPrimitive3D>
</Model3DCollection>
XAML支持引用资源的句法。在这个上下文中的“资源”是一个宽泛的术语,并且它既包含XAML文件的“资源”部分,也包含从受管理的程序集的受管理资源“派生(fork)”。两个机制都支持,并且可以从多处引用资源,以便共享它们。当前没有直接加载本地Win32资源的机制,然而,IResourceLoader接口的实现允许那么做。
尽管这与XAML不直接有关,但它与如何构建共享像网格和材料之类的对象的应用。注意,3D“建模”对象(Light,Model3DCollection,MeshPrimitive3D,Material,Mesh3D,Brush等等)是Changeable类型的。如上所述,changeable值提供在概念上产生深拷贝的Copy()方法,但事实上进行请求式浅-克隆。这个Copy()方法的使用导致对象的最优共享,同时仍允许那些对象的子部分改变。
二维“形状”,像Rectangle,Polygon,Ellipse等等,通过Shape类引入到Windows Presentation Framework(窗口显示框架)中,Shape类本身是UiElement。Shape像Rectangle一样可以放在Canvas上,后者本身是一个UiElement,目的用作形状的容器。下面是一个例子:
<Canvas Background=″black″Top=″100″Left=″100″Height=″600″Width=″800″>
 <Rectangle Top=”600”Left=”100”Width=”100”Height=”50”
   Fill=”red”Stroke=”blue”StrokeWidth=”10”/>
 <Line x1=″100″y1=″300″x2=″300″y2=″100″Stroke=”green”StrokeWidth=”5″/>
</Canvas>
这样,Canvas是一个UiElement,并且Rectangle和Line是不同的UiElement。包含在Canvas中的一切,在这种情况下,都是UiElement。
然而,考虑在标记中的组合Path,如这个例子示出:
<Canvas...>
  <Path Fill=”Red”Stroke=”Blue>
    <Path.Data>
      <CircleGeometry.../>
      <RectangleGeometry.../>
      <PathGeometry.../>
    </Path.Data>
  </Path>
</Canvas>
在这种情况下,CircleGeometry,RectangleGeometry(即在Path.Data内部的对象)本身不是UiElement,但Path容器是。
元素层“3D Shape”引起一个问题,因为Retained3DVisual的3D特征不超出Visual本身。即,两个Visual的内容从不在z方向互相穿插(例如,不能有穿透苹果视件的箭头视件)。由于Control和Shape从Visual派生,因此这也意味着不支持具有相互穿插的Control和Shape。它们始终是其内容的2D投影。
为具有在Effect层相互穿插的3D“对象”,并且还要在标记中表达它,提供Viewport3D元素,它可以包含具有所需的相互穿插的复杂3D模型。然而,它将不在z方向与任何其它Viewport3D交互(并且称为Viewport3D是因为它是进入3D空间的2D视见区)。
Viewport3D从派生Shape的同一个类派生(或者FrameworkElement或Control)。注意,Viewport3D不应当从Shape派生,因为Shape具有像Fill,Stroke等对3D没有意义的属性。因而,Viewport3D,Shape和Image都是同属。Viewport3D具有可以设置的许多属性,包括存在于Shape上的某些属性(Top,Left,Width,Height,Transform和Clip)。这些属性,尽管它们与3D无关,但对于3D的2D投影有意义,它是作为UiElement的Viewport3D的内容。
Viewport3D还具有与其相关联的Camera(并且提供合理的默认)以及像雾这样的3D场景级属性(即也在Retained3DVisual上的属性)。Viewport3D还具有以Model3DCollection为值的属性(它本身是Model3D),表示要通过该形状显示的3D对象的集合。这个模型还可以包括灯光。只要一个应用想要允许在z方向上交互,它就被放在单一Viewport3D的这个单一Model3DCollection中。
如果没有指定照相机,则使用默认的照相机提供投影,使得由Top,Left,Width,Height确定的Viewport3D边界用模型来填充,近/远剪辑就被设置在模型之前和之后,照相机俯视z轴,而y向上。如果没有指定灯光,则隐含地使用向下指着y轴的白色定向灯光。
Viewport3D的标记与上面所示Path的标记相似,由于它是在Path标记内指定非UiElement的例子。下面是Viewport3D标记的例子:
<Canvas...>
 <!--2D元素在这里,并且Viewport3D是2D元素。-->
<Viewport3D optionalCmera=″…″>
 <XFilePrimitive path=″...″/>
  <Mesh...>
   <BrushMaterial>
    <SolidColorBrush color=″yellow″>
   </BrushMaterial>
  </Mash>
  <Mesh...>
   <VisualMaterial>
    <VisualMaterial>
     <Button.../>
   </VisualMaterial>
  </Mesh>
  <SpotLight.../>
  <Model3DCollection Transform=″3DTransform″>
   <Mesh.../>
   <更多的模型,网格,灯光,分组等/>
  </Model3DCollection>
 </Viewport3D>
 <!--更多的2D元素-->
 <Rectangle.../>
</Canvas>
在<Viewport3D>标签内,以Model3DCollection为值的成员是从各个标记指定的Model3D填充的。注意,在这里的标签与Model3D的子类之间存在一对一的映射。而且,注意,在本例中的第二个Mesh具有一个包括标记指定的控件(本例中是Button)。这个控件将是完全交互的,并且可以指定OnClick等等。
Viewport3D的直接子节点是Model3D的,因为“默认”集合是Model集合。因而它的句法通常可改变为要求以复杂属性句法来描述<Viewport3D.Model>。这个标记将遵循正常2D标记所遵循的相同资源路径,例如,以定义Material并且在多处使用它。由一般的资源机制提供该功能。
通常,在UiElement或Control层发生击中测试。然而,可将击中测试限制于整个Viewport3D,或相反击中测试要求将模型分成多个Viewport3D并且在它们上击中测试。然而,一旦它们在多个Viewport3D中,它们就不再是同一3D环境的一部分。这是通过允许在标记或代码中在Model3D的各成员上指定事件处理程序以及一个“id”来分解的。当击中测试分解时,将调用适当的方法(发送者仍是整个Viewport3D),并且标识符将作为EventArg的一部分。然后应用能够或者在不同的事件处理程序中或者通过关掉“id”来隔离它们的逻辑。
VisualMaterial的使用向系统表示击中测试应当进入到该嵌入的元素中。系统保证这实际上一定发生。因而,击中测试操作从2D转到3D中并且回到2D中。下面是Viewport3D的API描述:
public class Viewport3D:UIElement//(或者
Control/FrameworkElement)
{
 //原料2D属性
 public BoxUnit Top{get;set;}
 public BoxUnit Left{get;set;}
 public BoxUnit Width{get;set;}
 public BoxUnit Height{get;set;}
 public Transform Transform{get;set;}
 public Geometry Clip{get;set;}
 //3D场景-层属性
 public Fog Fog{get;set;}
 public Camera Camera{get;set;}//具有好的默认
 //3D Model本身
 public Model3D Model{get;set;}
}
为在3D中正确地实现透明性,图元(以及,在极限情况下,各三角形)被排序以从后至前呈现,由此z-缓冲器不参与。这必须保证正在的混合。
还提供EmbeddingHostVisual。这是Visual的子类,它不能由外部各方来构建,而只能在内部构建。EmbeddingHostVisual包含一个Visual,它表示指定的Visual正被用作“嵌入的宿主”用于某种Visual对Visual关系而不是父亲/孩子关系。嵌入在3D场景中的2D Visual是它的另一个例子。Effect可以是在Visual之间的一种非-父亲/孩子关系的另一个例子。
下面阐述定义:
public class EmbeddingHostVisual:Visual
{
 internal EmbeddingHostVisual(Visual hostingVisual);//不能在外部构建
 public Visual HostingVisual{get;}
 //所有IVisual读服务将导致引起异常。
}
因为与EmbeddingHostVisual“父亲”的关系被定义为不是典型的父亲/孩子关系,意味着读服务如在Visual之间提取Transform没有意义,因为不存在均匀的映射。这些操作在3D子系统本身中处理,但注意该机制对于Retained3DVisual是唯一的。
媒体
MediaData可以用于通过下列对象播放任何音频/视频内容,并且也在附录中描述:
public System.Windows.Media.MediaData:Changeable,IDisposable,ITimingControl
{
 public MediaData(string source);
 //
 //MediaData属性
 //
 public MediaState State{get;}
 public Time MediaDurat ion{get;}
 public bool HasAudio{get;}
 public bool HasVideo{get;}
 public long Width{get;}
 public long Height{get;}
 public double Volume{get;set;}
 public bool Mute{get;set;}
//
//MediaData方法
//
public void Play();
//
//Changeable
//
public bool IsChangeable{get;}//默认为true
public Changeable Copy();
public Void MakeUnchangeable();
public UseStatus StatusOfNextUse{get;set;}//默认为false
public event EventHandler Changed{add;remove;}
public UIContext{get;}
//
//IDisposable接口
//
public void Dispose();
//
//ITimingControl接口
//
double Acceleration{get;set;}
bool AutoReverse{get;set;}
TimeSyncValue Begin{get;set;}
double Deceleration{get;set;}
Time Duration{get;set;}
TimeSyncValue End{get;set;}
TimeEndSync EndSync{get;set;}
TimeFill Fill{get;set;}
TimeFill FillDefault{get;set;}
Timeline ParentTimeline{get;set;}
double RepeatCount{get;set;}
Time RepeatDuration{get;set;}
TimeRestart Restart{get;set;}
TimeRestart RestarDefault{get;set;}
double Speed{get;set;}
int CurrentRepeat{get;}
Time CurrentTime{get;}
bool IsForwardProgressing{get;}
bool IsPaused{get;}
bool IsReversed{get;}
double Progress{get;}
bool IsChanging{get;}
bool IsEnabled{get;}
bool IsOverridingBaseValue{get;}
bool HasChanged{get;}
void Enable();
void Enable(Timeline parentTimeline);
void Disable();
void BeginIn(Time offset);
void EndIn(Time offset);
void Pause();
void Resume();
void Seek(Time offset,TimeSeekOrigin origin);
event EventHandler Begun{add;remove;}
event EventHandler Ended{add;remove;}
event EventHandler Paused{add;remove;}
event EventHandler Repeated{add;remove;}
event EventHandler Resumed{add;remove;}
event EventHandler Reversed{add;remove;}
  event EventHandler Seeked{add;remove;}
}
为音频数据提供AudioData对象:
 public System.Windows.Media.AudioData:MediaData
 {
   public AudioData(string source);
 //
 //MediaData
 //
 public MediaState State{get;}
 public Time MediaDurnation{get;}
 public bool HasAudio{get;}
 public bool HasVideo{get;}
 public long Width{get;}
 public long Height{get;}
 public double Volume{get;set;}
 public bool Mute{get;set;}
 public Void Play();
 pubiic void Dispose();
 public bool IsChange{get;}//默认为true
 public Changeable Copy();
 public void MakeUnchangeable();
 public UseStatus StatusOfNextUse{get;set;}//默认为false
 public event EventHandler Changed{add;remove;}
 public UIContext UIContext{get;}
 double Acceleration{get;set;}
 bool AutoReverse{get;set;}
 TimeSyncValue Begin{get;set;}
 double Deceleration{get;set;}
Time Duration{get;set;}
TimeSyncValue End{get;set;}
TimeEndSync EndSync{get;set;}
TimeFill Fill{get;set;}
TimeFill FillDefault{get;set;}
Timeline ParentTimeline{get;set;}
double RepeatCouut{get;set;}
Time RepeatDuration{get;set;}
TimeRestart Restart{get;set;}
TimeRestart RestartDefault{get;set;}
double Speed{get;set;}
int CurrentRepeat{get;}
Time CurrentTime{get;}
bool IsForwardProgressing{get;}
bool IsPaused{get;}
bool IsReversed{get;}
double Progress{get;}
bool IsChanging{get;}
bool IsEnabled{get;}
bool IsOverridingBaseValue{get;}
bool HasChanged{get;}
void Enable();
void Enable(Timeline parentTimeline);
void Disable();
void BeginIn(Time offset);
void EndIe(Time offset);
void Pause();
void Resume();
void Seek(Time offset,TimeSeekOrigin origin);
event EventHandler Begun{add;remove;}
event EventHandler Ended{add;remove;}
event EventHandler Paused{ add;remove;}
   event EventHandler Repeated{add;remove;}
   event EventHandler Resumed{add;remove;}
   event EventHandler Reversed{add;remove;}
   event EventHandler Seeked{add;remove;}
 }
为视频数据提供VideoData:
public system.Windows.MediaVideoData:MediaData
{
 public VideoData(string source);
 //
 //MediaData
  //
  public MediaState State{get;}
  public Time MediaDuration{get;}
  public bool HasAudio{get;}
  public bool HasVideo{get;}
  public long Width{get;}
  public long Height{get;}
  public double Volume{get;set;}
  public bool Mute{get;set;}
  public void Play();
  public void Dispose();
public bool IsChange{get;}//默认为true
 public Changeable Copy();
 public void MakeUnchangeable();
 public UseStatus StatusOfNextUse{get;set;}//默认为false
 public event EventHandler Changed{add;remove;}
 public UIContext UIContext{get;}
      double Acceleration{get;set;}
      bool AutoReverse{get;set;}
      bool IsOverridingBaseValue{get;}
      bool HasChanged{get;}
      void Enable();
      void Enable(Timeline parentTimeline);
      void Disable();
      void BeginIn(Time offset);
      void EndIn(Time offset);
      void Pause();
      void Resume();
      void Seek(Time offset,TimeSeekOrigin origin);
      event EventHandler Begun{add;remove;}
      event EventHandler Ended{add;remove;}
      event EventHandler Paused{add;remove;}
      event EventHandler Repeated{add;remove;}
      event EventHandler Resumed{add;remove;}
      event EventHandler Reversed{add;remove;}
      event EventHandler Seeked{add;remove;}
  }
还提供元素层Video对象:
public System.Windows.Controls.Video:FrameworkElement
{
  public Video();
  //
//Video Element属性
//
 public VideoData Source{get;set;}
 public MediaState MediaState{get;}
 public double Volume{get;set;}
 public bool Mute{get;set;}
 public int NativeVideoHeight{get;}
 public int NativeVideoWidth{get;}
 public Time MediaDuration{get;}
 public TimeSyncValue Begin{get;set;}
 public TimeSyncValue End{get;set;}
 public Time Duration{get;set;}
 public double RepeatCount{get;set;}
 public Time RepeatDuration{get;set;}
 public HorizontalAlignment HorizontalAlignment{get;set;}
 public VerticalAlignment VerticalAlignment{get;set;}
 public Stretch Stretch{get;set;}
//
 //Video Element方法
 //
 public void BeginIn(Time offset);
 public void EndIn(Time offset);
 public void Pause();
 public void Resume();
 public void Seek(Time offset,TimeSeekOrigin origin);
}
还提供元素层Audio对象:
 public System.Windows.Controls.Audio:FrameworkElemcnt
 {
   public Audio();
//
//Audio Element属性
//
  public AudioData Source{get;set;}
  public MediaState MediaState{get;}
  public double Volume{get;set;}
  public bool Mute{get;set;}
  public Time MediaDuration{get;}
  public TimeSyncValue Begin{get;set;}
  public TimeSyncValue End{get;set;}
  public Time Duration{get;set;}
  public double RepeatCount{get;set;}
  public Time RepeatDuretion{get;set;}
//
//Audio Element方法
//
  //
  //Audio Element methods
  //
  public void BeginIn(Time offset);
  public void EndIn(Time offset);
  public void Pause();
  public void Resume();
  public void Seek(Time offset,TimeSeekOrigin origin);
}
结论
正如从前面的详细描述中可看到的,提供了一种媒体集成层,它包括为程序代码提供与场景图接口的能力的接口和对象模型。该系统、方法和对象模型是直接可用的,而且强大、灵活、可扩展。
尽管易于从本发明得到各种变型和替换结构,但其某些说明实施例还是示出在附图中并在前面详细描述。但是应该理解,没有将本发明限制于所公开的特定形式的意图,恰恰相反,旨在覆盖落在本发明的精神和范围内的所有变型、替换结构和等价方案。

Claims (67)

1.一种用于安排计算机图形数据用于处理到输出中的方法,其特征在于,包括:
通过媒体集成层的接口接收函数调用,所述函数调用对应于图形相关数据;以及
基于所述函数调用使场景图数据结构中的数据被修改。
2.如权利要求1所述的方法,其特征在于,所述使场景图数据结构中的数据被修改包括调用初始化视件类新实例的函数。
3.如权利要求2所述的方法,其特征在于,还包括,通过对应于关联于所述视件的变换的接口接收函数调用。
4.如权利要求1所述的方法,其特征在于,所述使场景图数据结构中的数据被修改包括调用初始化绘制视件类新实例的函数。
5.如权利要求4所述的方法,其特征在于,还包括,通过接口接收函数调用,以打开所述绘制视件实例用于呈现,且作为响应,使绘制上下文被返回,所述绘制上下文提供呈现到所述绘制视件中的机制。
6.如权利要求1所述的方法,其特征在于,还包括,接收关联于所述函数调用的画刷数据,且其中,使场景图数据结构中的数据被修改包括调用修改所述场景图数据结构中的数据结构的画刷函数,从而当一帧从所述场景图呈现时,将用对应于所述画刷数据的可视数据填充一区域。
7.如权利要求6所述的方法,其特征在于,接收画刷数据包括接收对应于纯色的数据。
8.如权利要求6所述的方法,其特征在于,接收画刷数据包括接收对应于线性渐变画刷和至少包括一个停止符的停止符集合的数据。
9.如权利要求6所述的方法,其特征在于,接收画刷数据包括接收对应于径向渐变画刷的数据。
10.如权利要求6所述的方法,其特征在于,接收画刷数据包括接收对应于图像的数据。
11.如权利要求10所述的方法,其特征在于,还包括通过对应于应用于图像的图像效果的接口接收函数调用。
12.如权利要求1所述的方法,其特征在于,还包括,接收关联于所述函数调用的笔数据,且其中,使场景图数据结构中的数据被修改包括调用定义形状轮廓的笔函数。
13.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括调用表示所述场景图数据结构中的椭圆的几何图形相关的函数。
14.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括调用表示所述场景图数据结构中的矩形的几何图形相关的函数。
15.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括调用表示所述场景图数据结构中的路径的几何图形相关的函数。
16.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括调用表示所述场景图数据结构中的直线的几何图形相关的函数。
17.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括调用与击中测试所述场景图数据结构中视件有关的函数。
18.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括调用与变换所述场景图数据结构中视件坐标有关的函数。
19.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括调用与计算所述场景图数据结构中视件的边界框有关的函数。
20.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括通过对所述场景图数据结构中视件对象的公共接口调用一函数。
21.如权利要求1所述的方法,其特征在于,还包括调用呈现至少一个视件对象的树到呈现目标的视件管理器。
22.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括调用将容器对象放在所述场景图数据结构中的函数,所述容器对象被配置为包含至少一个视件对象。
23.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括调用将图像数据放在所述场景图数据结构中的函数。
24.如权利要求23所述的方法,其特征在于,使场景图数据结构中的数据被修改包括调用将图像效果对象放在关联于所述图像数据的场景图数据结构中的函数。
25.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括调用将对应于文本的数据放在所述场景图数据结构中的函数。
26.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括调用响应于所述函数调用提供绘制上下文的函数。
27.如权利要求26所述的方法,其特征在于,所述函数调用对应于保留视件,且还包括,回调使所述保留视件的绘制上下文返回到所述场景图数据结构。
28.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括调用将三维视件放到所述场景图数据结构中的函数。
29.如权利要求28所述的方法,其特征在于,使场景图数据结构中的数据被修改包括将二维表面映射到三维视件上。
30.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括调用将动画数据放入所述场景图数据结构中的函数。
31.如权利要求30所述的方法,其特征在于,还包括将对应于所述动画数据的时间线信息传送到在所述媒体集成层另一层处的合成引擎。
32.如权利要求31的方法,其特征在于,所述合成引擎基于时间线内插图形数据,使对应于所述场景图数据结构中对象的输出动画化。
33.如权利要求1所述的方法,其特征在于,通过媒体集成层的接口接收函数调用包括接收标记,且其中,使场景图数据结构中的数据被修改包括将所述标记分析成对一对象的接口的调用。
34.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括调用将对应于音频和/或视频数据的对象放到所述场景图数据结构中的函数。
35.如权利要求1所述的方法,其特征在于,使场景图数据结构中的数据被修改包括改变所述场景图数据结构中对象的可变值。
36.在一计算环境中,一种系统,包括:
一分层系统的场景图数据结构,用于包含可呈现到输出中的数据,所述输出用于可观看的后续集成输出;以及
一对象模型,包括可以包含在所述场景图数据结构中的对象和其它数据,至少所述对象模型中的一些对象具有用于调用修改所述场景图数据结构内容的函数的接口。
37.如权利要求26所述的系统,其特征在于,至少调用一个函数来将一视件对象树放到所述场景图数据结构中。
38.如权利要求37所述的系统,其特征在于,还包括一视件管理器,当调用时将所述视件对象树呈现给呈现目标。
39.如权利要求37所述的系统,其特征在于,所述视件对象树包含在视件集合对象中。
40.如权利要求26所述的系统,其特征在于,至少调用一个函数来将视件对象放到所述场景图数据结构中。
41.如权利要求40所述的系统,其特征在于,至少调用一个函数来将画刷关联于所述视件对象。
42.如权利要求40所述的系统,其特征在于,至少调用一个函数来将几何形状关联于所述视件对象。
43.如权利要求42所述的系统,其特征在于,所述几何图形包括包含椭圆几何图形、矩形几何图形、直线几何图形和路径几何图形的集合的至少一个。
44.如权利要求40所述的系统。其特征在于,至少调用一个函数来将变换关联于所述视件对象。
45.如权利要求44所述的系统,其特征在于,所述变换包括旋转变换,来改变所述视件对象的感知角度。
46.如权利要求44所述的系统,其特征在于,所述变换包括缩放变换,来改变所述视件对象的感知尺寸。
47.如权利要求44所述的系统,其特征在于,所述变换包括转换变换,来改变所述视件对象的感知位置。
48.如权利要求44所述的系统,其特征在于,所述变换包括偏斜变换,来改变所述视件对象的感知偏斜。
49.如权利要求44所述的系统,其特征在于,还包括关联于所述变换的动画信息,且其中,所述动画信息使关联于所述变换的变换数据随时间而变化,从而使所述视件对象的变换随时间动画化。
50.如权利要求40所述的系统,其特征在于,至少调用一个函数来将颜色关联于所述视件对象。
51.如权利要求40所述的系统,其特征在于,至少调用一个函数来将渐变数据关联于所述视件对象。
52.如权利要求40所述的系统,其特征在于,至少调用一个函数来将平铺画刷关联于所述视件对象。
53.如权利要求40所述的系统,其特征在于,至少调用一个函数来将图像关联于所述视件对象。
54.如权利要求40所述的系统,其特征在于,至少调用一个函数来将三维数据关联于所述视件对象。
55.如权利要求40所述的系统,其特征在于,至少调用一个函数来将包括绘制图元的绘制关联于所述视件对象。
56.如权利要求40所述的系统,其特征在于,至少调用一个函数来将音频和/或视频媒体关联于所述视件对象。
57.如权利要求40所述的系统,其特征在于,至少调用一个函数来将图像效果关联于所述视件对象。
58.如权利要求40所述的系统,其特征在于,至少调用一个函数来将笔关联于所述视件对象,来描述如何描画形状的轮廓。
59.如权利要求40所述的系统,其特征在于,至少调用一个函数来获得关联于所述视件对象的绘制上下文。
60.如权利要求40所述的系统,其特征在于,至少调用一个函数来将击中测试数据关联于所述视件对象。
61.如权利要求40所述的系统,其特征在于,至少调用一个函数来将矩形关联于所述视件对象。
62.如权利要求61所述的系统,其特征在于,至少调用一个函数来描述源矩形应如何拉伸以适合对应于所述视件对象的目的地矩形。
63.如权利要求61所述的系统,其特征在于,至少调用一个函数来描述内容如何垂直定位在对应于所述视件对象的容器内。
64.如权利要求61所述的系统,其特征在于,至少调用一个函数来描述内容如何水平定位在对应于所述视件对象的容器内。
65.在一计算环境中,一种系统,包括:
用于接收函数调用的接口装置;
用于将通过所述接口装置接收的图形相关的数据和/或媒体相关的数据集成为场景图的高层合成装置;以及
用于将所述场景图转换成可传输或显示的输出的呈现装置。
66.如权利要求65所述的系统,其特征在于,所述呈现装置包括用于基于从所述高层合成引擎接收到的数据构建用于观看的帧的低层合成装置。
67.如权利要求65所述的系统,其特征在于,还包括动画装置,所述高层合成引擎提供时间线数据给所述低层合成装置,用于内插跨至少两个帧的可视数据的外观,使所述可视数据随时间动画化。
CNA2004800014899A 2003-10-23 2004-07-28 媒体集成层 Pending CN1989543A (zh)

Applications Claiming Priority (2)

Application Number Priority Date Filing Date Title
US10/693,630 US7511718B2 (en) 2003-10-23 2003-10-23 Media integration layer
US10/693,630 2003-10-23

Publications (1)

Publication Number Publication Date
CN1989543A true CN1989543A (zh) 2007-06-27

Family

ID=34573199

Family Applications (1)

Application Number Title Priority Date Filing Date
CNA2004800014899A Pending CN1989543A (zh) 2003-10-23 2004-07-28 媒体集成层

Country Status (14)

Country Link
US (1) US7511718B2 (zh)
EP (1) EP1623406A4 (zh)
JP (1) JP2007509426A (zh)
KR (1) KR20070028202A (zh)
CN (1) CN1989543A (zh)
AU (1) AU2004279199A1 (zh)
BR (1) BRPI0406378A (zh)
CA (1) CA2501452A1 (zh)
NO (1) NO20052269L (zh)
NZ (1) NZ540116A (zh)
RU (1) RU2360275C2 (zh)
TW (1) TW200515304A (zh)
WO (1) WO2005045584A2 (zh)
ZA (1) ZA200503159B (zh)

Cited By (7)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN101986307A (zh) * 2010-11-11 2011-03-16 东莞宇龙通信科技有限公司 一种mime类型插件的生成方法、系统及浏览器
CN103198471A (zh) * 2013-02-28 2013-07-10 天脉聚源(北京)传媒科技有限公司 一种视频的裁切方法及装置
CN106658145A (zh) * 2016-12-27 2017-05-10 北京奇虎科技有限公司 一种直播数据处理方法和装置
CN110297657A (zh) * 2019-06-11 2019-10-01 东南大学 一种基于层次上下文的api推荐方法
CN110764757A (zh) * 2019-10-22 2020-02-07 成都九洲电子信息系统股份有限公司 一种基于html5的交互式图形绘制引擎
CN113326031A (zh) * 2021-05-28 2021-08-31 网易(杭州)网络有限公司 属性获取方法和装置
TWI786321B (zh) * 2014-10-06 2022-12-11 美商Vid衡器股份有限公司 用於解碼/編碼的方法及裝置、計算機程式產品、計算機程式及視訊資料

Families Citing this family (173)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US7330186B2 (en) * 1999-08-03 2008-02-12 Sony Corporation Methods and systems for scoring multiple time-based assets and events
US7456845B2 (en) * 2000-10-30 2008-11-25 Microsoft Corporation Efficient perceptual/physical color space conversion
US6954214B2 (en) * 2000-10-30 2005-10-11 Microsoft Corporation Efficient perceptual/physical color space conversion
US20030128214A1 (en) * 2001-09-14 2003-07-10 Honeywell International Inc. Framework for domain-independent archetype modeling
US7161599B2 (en) * 2001-10-18 2007-01-09 Microsoft Corporation Multiple-level graphics processing system and method
US7619633B2 (en) 2002-06-27 2009-11-17 Microsoft Corporation Intelligent caching data structure for immediate mode graphics
US7612776B2 (en) * 2002-09-14 2009-11-03 Microsoft Corporation Functions acting on arbitrary geometric paths
US20080195925A1 (en) * 2003-06-26 2008-08-14 Donna Marie Auguste Compressed Media Files with Intrinsic Supplementary Content
US7219340B2 (en) * 2003-10-23 2007-05-15 Microsoft Corporation Changeable class and pattern to provide selective mutability in computer programming environments
US7068284B2 (en) * 2003-11-10 2006-06-27 Microsoft Corporation Color management system that supports legacy and advanced color management applications
US7454696B2 (en) * 2004-04-09 2008-11-18 International Business Machines Corporation Method and apparatus for stream based markup language post-processing
KR100601952B1 (ko) * 2004-04-20 2006-07-14 삼성전자주식회사 3차원 그래픽 데이터의 재구성장치 및 방법
US20050243085A1 (en) * 2004-05-03 2005-11-03 Microsoft Corporation Model 3D construction application program interface
US8031190B2 (en) * 2004-05-03 2011-10-04 Microsoft Corporation Translating two-dimensional user input on three-dimensional scene
US7145562B2 (en) * 2004-05-03 2006-12-05 Microsoft Corporation Integration of three dimensional scene hierarchy into two dimensional compositing system
US8130237B2 (en) * 2004-06-24 2012-03-06 Apple Inc. Resolution independent user interface design
US8068103B2 (en) 2004-06-24 2011-11-29 Apple Inc. User-interface design
US7719523B2 (en) 2004-08-06 2010-05-18 Touchtable, Inc. Bounding box gesture recognition on a touch detecting interactive display
US20090019084A1 (en) * 2004-10-04 2009-01-15 T. Rad Co., Ltd. Method and system for preloading
US7603624B2 (en) * 2004-10-21 2009-10-13 Microsoft Corporation System and method for styling content in a graphical user interface control
EP1681656A1 (en) * 2005-01-18 2006-07-19 Oculus Info Inc. System and method for processing map data
US7154503B2 (en) * 2005-03-31 2006-12-26 Microsoft Corporation Methods and systems for brush composition
US7561159B2 (en) * 2005-05-31 2009-07-14 Magnifi Group Inc. Control of animation timeline
US8108787B2 (en) * 2005-07-01 2012-01-31 Microsoft Corporation Distributing input events to multiple applications in an interactive media environment
US20070006062A1 (en) * 2005-07-01 2007-01-04 Microsoft Corporation Synchronization aspects of interactive multimedia presentation management
US20070006079A1 (en) * 2005-07-01 2007-01-04 Microsoft Corporation State-based timing for interactive multimedia presentations
US8020084B2 (en) * 2005-07-01 2011-09-13 Microsoft Corporation Synchronization aspects of interactive multimedia presentation management
US8799757B2 (en) * 2005-07-01 2014-08-05 Microsoft Corporation Synchronization aspects of interactive multimedia presentation management
US20070006078A1 (en) * 2005-07-01 2007-01-04 Microsoft Corporation Declaratively responding to state changes in an interactive multimedia environment
US20070006238A1 (en) * 2005-07-01 2007-01-04 Microsoft Corporation Managing application states in an interactive media environment
US8305398B2 (en) * 2005-07-01 2012-11-06 Microsoft Corporation Rendering and compositing multiple applications in an interactive media environment
US7941522B2 (en) * 2005-07-01 2011-05-10 Microsoft Corporation Application security in an interactive media environment
US8656268B2 (en) * 2005-07-01 2014-02-18 Microsoft Corporation Queueing events in an interactive media environment
JP4864432B2 (ja) * 2005-11-29 2012-02-01 京セラ株式会社 イベント駆動型アプリケーションにおけるイベント配送方法
US7737996B2 (en) * 2005-12-01 2010-06-15 Microsoft Corporation Techniques for automated animation
US8077174B2 (en) * 2005-12-16 2011-12-13 Nvidia Corporation Hierarchical processor array
US7898542B1 (en) * 2006-03-01 2011-03-01 Adobe Systems Incorporated Creating animation effects
JP4881048B2 (ja) * 2006-04-03 2012-02-22 キヤノン株式会社 情報処理装置および情報処理方法および情報処理プログラム
KR100783679B1 (ko) * 2006-05-11 2007-12-07 한국과학기술원 데이터 스트림에 기반하는 서비스의 개발, 배치, 제공을용이하게 하는 미들웨어 시스템
US7868879B2 (en) * 2006-05-12 2011-01-11 Doremi Labs, Inc. Method and apparatus for serving audiovisual content
US7890533B2 (en) * 2006-05-17 2011-02-15 Noblis, Inc. Method and system for information extraction and modeling
US20070268304A1 (en) * 2006-05-22 2007-11-22 Microsoft Corporation Gradient Brush and Stroke
US7825937B1 (en) * 2006-06-16 2010-11-02 Nvidia Corporation Multi-pass cylindrical cube map blur
US8860752B2 (en) * 2006-07-13 2014-10-14 Apple Inc. Multimedia scripting
US9019300B2 (en) 2006-08-04 2015-04-28 Apple Inc. Framework for graphics animation and compositing operations
US8130226B2 (en) * 2006-08-04 2012-03-06 Apple Inc. Framework for graphics animation and compositing operations
US20080055315A1 (en) * 2006-09-05 2008-03-06 Dale Ducharme Method and System to Establish and Animate a Coordinate System for Content on a Display
US20080084416A1 (en) * 2006-10-06 2008-04-10 Microsoft Corporation User-pluggable rendering engine
US8782277B2 (en) * 2006-10-12 2014-07-15 Siemens Product Lifecycle Management Software Inc. System and method for time-sensitive URI mapping
WO2008055034A2 (en) 2006-10-30 2008-05-08 Noblis, Inc. Method and system for personal information extraction and modeling with fully generalized extraction contexts
US8234392B2 (en) 2006-11-17 2012-07-31 Apple Inc. Methods and apparatuses for providing a hardware accelerated web engine
US20080130987A1 (en) * 2006-11-30 2008-06-05 Microsoft Corporation Color Management of RAW Content from Digital Capture Devices
US20080158254A1 (en) * 2006-12-29 2008-07-03 Hong Jiang Using supplementary information of bounding boxes in multi-layer video composition
WO2008087912A1 (ja) * 2007-01-15 2008-07-24 Panasonic Corporation 表示処理装置、表示処理方法および表示処理プログラム
US8074227B2 (en) * 2007-02-08 2011-12-06 Microsoft Corporation Utilizing a first managed process to host at least a second managed process
US9519997B1 (en) * 2007-03-09 2016-12-13 Pixar Perfect bounding for optimized evaluation of procedurally-generated scene data
US20080244511A1 (en) * 2007-03-30 2008-10-02 Microsoft Corporation Developing a writing system analyzer using syntax-directed translation
US8108799B2 (en) * 2007-03-30 2012-01-31 Microsoft Corporation Remoting of windows presentation framework based applications in a non-composed desktop
US20080250424A1 (en) * 2007-04-04 2008-10-09 Ms1 - Microsoft Corporation Seamless Window Implementation for Windows Presentation Foundation based Applications
US20130342433A9 (en) * 2007-04-14 2013-12-26 Ananth Sankar Dynamic backlight control for video displays
US8134556B2 (en) * 2007-05-30 2012-03-13 Elsberg Nathan Method and apparatus for real-time 3D viewer with ray trace on demand
US20090021513A1 (en) * 2007-07-18 2009-01-22 Pixblitz Studios Inc. Method of Customizing 3D Computer-Generated Scenes
US8884981B2 (en) * 2007-09-04 2014-11-11 Apple Inc. Dynamically reconfigurable graphics layer system and method
US7941758B2 (en) * 2007-09-04 2011-05-10 Apple Inc. Animation of graphical objects
JP5424546B2 (ja) * 2007-09-13 2014-02-26 京セラドキュメントソリューションズ株式会社 画像処理装置及び画像形成システム
US8126826B2 (en) 2007-09-21 2012-02-28 Noblis, Inc. Method and system for active learning screening process with dynamic information modeling
US8661096B2 (en) * 2007-11-05 2014-02-25 Cyberlink Corp. Collaborative editing in a video editing system
JP2009129127A (ja) * 2007-11-22 2009-06-11 Fujitsu Ltd プログラムの不変物抽出処理プログラム,処理装置,および処理方法,ならびに該プログラムを記憶する記憶媒体
US8397207B2 (en) * 2007-11-26 2013-03-12 Microsoft Corporation Logical structure design surface
US8009921B2 (en) * 2008-02-19 2011-08-30 Xerox Corporation Context dependent intelligent thumbnail images
US8482568B2 (en) * 2008-03-03 2013-07-09 Pixar Systems and methods for specifying arbitrary animation controls for model objects
US9251548B1 (en) 2008-03-31 2016-02-02 The Mathworks, Inc. Object transformation for object trees utilized with multiprocessor systems
US8300060B1 (en) * 2008-03-31 2012-10-30 The Mathworks, Inc. Object transformation for object trees utilized with multiprocessor systems
US8760472B2 (en) * 2008-04-01 2014-06-24 Apple Inc. Pixel transforms
EP2109304A1 (en) * 2008-04-07 2009-10-14 Océ-Technologies B.V. Color management method, module, and program product, and printer ussing said method
US9052924B2 (en) * 2008-04-15 2015-06-09 Microsoft Technology Licensing, Llc Light-weight managed composite control hosting
US9589381B2 (en) * 2008-06-12 2017-03-07 Microsoft Technology Licensing, Llc Copying of animation effects from a source object to at least one target object
US8290971B2 (en) * 2008-09-09 2012-10-16 Applied Systems, Inc. Method and apparatus for remotely displaying a list by determining a quantity of data to send based on the list size and the display control size
US8645822B2 (en) * 2008-09-25 2014-02-04 Microsoft Corporation Multi-platform presentation system
US20100079474A1 (en) * 2008-09-30 2010-04-01 Microsoft Corporation Methods for rendering source content of a file for display on a destination figure
US8508537B2 (en) * 2008-11-17 2013-08-13 Disney Enterprises, Inc. System and method for dependency graph evaluation for animation
US8587610B2 (en) * 2008-12-12 2013-11-19 Microsoft Corporation Rendering source content for display
KR101194605B1 (ko) * 2008-12-22 2012-10-25 한국전자통신연구원 시간 연속적 텍스쳐 합성 장치 및 방법
US8174541B2 (en) * 2009-01-19 2012-05-08 International Business Machines Corporation Dividing three-dimensional space into location based virtual packets
US8477136B2 (en) * 2009-02-13 2013-07-02 Mobitv, Inc. Functional presentation layer in a lightweight client architecture
US8819570B2 (en) * 2009-03-27 2014-08-26 Zumobi, Inc Systems, methods, and computer program products displaying interactive elements on a canvas
US9142044B2 (en) * 2009-05-26 2015-09-22 Oracle International Corporation Apparatus, systems and methods for layout of scene graphs using node bounding areas
US8471858B2 (en) * 2009-06-02 2013-06-25 Qualcomm Incorporated Displaying a visual representation of performance metrics for rendered graphics elements
US20100310193A1 (en) * 2009-06-08 2010-12-09 Castleman Mark Methods and apparatus for selecting and/or displaying images of perspective views of an object at a communication device
US20100312813A1 (en) * 2009-06-08 2010-12-09 Castleman Mark Methods and apparatus for distributing, storing, and replaying directives within a network
US20100313249A1 (en) * 2009-06-08 2010-12-09 Castleman Mark Methods and apparatus for distributing, storing, and replaying directives within a network
US20100311393A1 (en) * 2009-06-08 2010-12-09 Castleman Mark Methods and apparatus for distributing, storing, and replaying directives within a network
US8286084B2 (en) * 2009-06-08 2012-10-09 Swakker Llc Methods and apparatus for remote interaction using a partitioned display
US20100309196A1 (en) * 2009-06-08 2010-12-09 Castleman Mark Methods and apparatus for processing related images of an object based on directives
WO2010144429A1 (en) * 2009-06-08 2010-12-16 Swakker Llc Methods and apparatus for processing related images of an object based on directives
US20100313244A1 (en) * 2009-06-08 2010-12-09 Castleman Mark Methods and apparatus for distributing, storing, and replaying directives within a network
JP5371596B2 (ja) * 2009-07-13 2013-12-18 キヤノン株式会社 情報処理装置、情報処理方法及びプログラム
US20110022978A1 (en) * 2009-07-23 2011-01-27 Rockwell Automation Technologies, Inc. Intelligent device framework
KR101277274B1 (ko) * 2009-11-27 2013-06-20 한국전자통신연구원 자원 간의 물리적/논리적 관계를 맵핑하는 방법 및 장치
US9021390B1 (en) * 2010-05-05 2015-04-28 Zynga Inc. Methods and apparatus for optimized pausing of an embedded application to render pop-up window
US8719774B2 (en) * 2010-07-30 2014-05-06 National Instruments Corporation Developing programs for hardware implementation in a graphical specification and constraint language Via iterative estimation of performance or resource utilization
JP2012060280A (ja) * 2010-09-07 2012-03-22 Sony Corp 情報処理装置、情報処理方法、およびプログラム
US9396001B2 (en) 2010-11-08 2016-07-19 Sony Corporation Window management for an embedded system
US8689123B2 (en) 2010-12-23 2014-04-01 Microsoft Corporation Application reporting in an application-selectable user interface
US9176742B2 (en) * 2010-12-27 2015-11-03 Microsoft Technology Licensing, Llc Converting desktop applications to web applications
US8836699B2 (en) * 2011-02-04 2014-09-16 Chiung Yu Chen Generation of landmark architecture and sculpture based on chinese characters
US8982132B2 (en) * 2011-02-28 2015-03-17 Adobe Systems Incorporated Value templates in animation timelines
US20130127849A1 (en) * 2011-05-26 2013-05-23 Sebastian Marketsmueller Common Rendering Framework and Common Event Model for Video, 2D, and 3D Content
EP2549389A1 (en) * 2011-07-20 2013-01-23 Axel Springer Digital TV Guide GmbH Easy 2D navigation in a video database
US9563971B2 (en) 2011-09-09 2017-02-07 Microsoft Technology Licensing, Llc Composition system thread
US8687018B1 (en) 2011-09-23 2014-04-01 Google Inc. Collection and confirmation of place metadata and graphic representations of fixed objects displayed in a mapping system
US8954475B2 (en) 2011-11-10 2015-02-10 Microsoft Technology Licensing, Llc Deep cloning of objects using binary format
US9384711B2 (en) 2012-02-15 2016-07-05 Microsoft Technology Licensing, Llc Speculative render ahead and caching in multiple passes
US9373049B1 (en) * 2012-04-05 2016-06-21 Amazon Technologies, Inc. Straight line gesture recognition and rendering
US9098186B1 (en) 2012-04-05 2015-08-04 Amazon Technologies, Inc. Straight line gesture recognition and rendering
US20130278607A1 (en) * 2012-04-20 2013-10-24 A Thinking Ape Technologies Systems and Methods for Displaying Animations on a Mobile Device
RU2485593C1 (ru) * 2012-05-10 2013-06-20 Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования "Сибирская государственная геодезическая академия" (ФГБОУ ВПО "СГГА") Способ построения перспективных карт местности (варианты)
KR101997129B1 (ko) * 2012-05-17 2019-10-01 엘지전자 주식회사 사이니지 콘텐츠 생성 방법
US9235925B2 (en) * 2012-05-31 2016-01-12 Microsoft Technology Licensing, Llc Virtual surface rendering
US9286122B2 (en) 2012-05-31 2016-03-15 Microsoft Technology Licensing, Llc Display techniques using virtual surface allocation
US9177533B2 (en) 2012-05-31 2015-11-03 Microsoft Technology Licensing, Llc Virtual surface compaction
US9230517B2 (en) 2012-05-31 2016-01-05 Microsoft Technology Licensing, Llc Virtual surface gutters
US9021437B2 (en) * 2012-07-13 2015-04-28 Microsoft Technology Licensing, Llc Declarative style rules for default touch behaviors
US10824680B2 (en) 2012-10-02 2020-11-03 The Boeing Company Panoptic visualization document access control
US9659237B2 (en) * 2012-10-05 2017-05-23 Micro Usa, Inc. Imaging through aerosol obscurants
US9075618B2 (en) * 2012-11-02 2015-07-07 Microsoft Technology Licensing, Llc Cross-platform data visualizations using common descriptions
WO2014091385A1 (en) * 2012-12-10 2014-06-19 Koninklijke Philips N.V. Method and system for making multisite performance measure anonymous and for controlling actions and re-identification of anonymous data
US20150379906A1 (en) * 2012-12-21 2015-12-31 3M Innovative Properties Company Systems and methods for rule-based animated content optimization
US9098269B2 (en) * 2013-01-04 2015-08-04 Microsoft Technology Licensing, Llc System and method to ensure resource access safety with immutable object types
GB201304321D0 (en) * 2013-03-11 2013-04-24 Creative Edge Software Llc Apparatus and method for applying a two-dimensional image on a three-dimensional model
US9171401B2 (en) 2013-03-14 2015-10-27 Dreamworks Animation Llc Conservative partitioning for rendering a computer-generated animation
US9224239B2 (en) 2013-03-14 2015-12-29 Dreamworks Animation Llc Look-based selection for rendering a computer-generated animation
US9659398B2 (en) 2013-03-15 2017-05-23 Dreamworks Animation Llc Multiple visual representations of lighting effects in a computer animation scene
US9811936B2 (en) 2013-03-15 2017-11-07 Dreamworks Animation L.L.C. Level-based data sharing for digital content production
US9626787B2 (en) 2013-03-15 2017-04-18 Dreamworks Animation Llc For node in render setup graph
US9218785B2 (en) 2013-03-15 2015-12-22 Dreamworks Animation Llc Lighting correction filters
US9589382B2 (en) * 2013-03-15 2017-03-07 Dreamworks Animation Llc Render setup graph
US9208597B2 (en) 2013-03-15 2015-12-08 Dreamworks Animation Llc Generalized instancing for three-dimensional scene data
US9230294B2 (en) 2013-03-15 2016-01-05 Dreamworks Animation Llc Preserving and reusing intermediate data
US9514562B2 (en) 2013-03-15 2016-12-06 Dreamworks Animation Llc Procedural partitioning of a scene
US9307007B2 (en) 2013-06-14 2016-04-05 Microsoft Technology Licensing, Llc Content pre-render and pre-fetch techniques
US9177413B2 (en) * 2013-06-26 2015-11-03 Nvidia Corporation Unique primitive identifier generation
US9942622B2 (en) * 2014-01-24 2018-04-10 Hiperwall, Inc. Methods and systems for synchronizing media stream presentations
US9477998B2 (en) * 2014-06-01 2016-10-25 Apple Inc. Performance control for concurrent animations
KR20160030701A (ko) * 2014-09-11 2016-03-21 삼성전자주식회사 인쇄 데이터를 프린터로 전송하는 호스트 디바이스 및 호스트 디바이스가 인쇄 데이터를 렌더링하는 방법
US20160104307A1 (en) * 2014-10-14 2016-04-14 Microsoft Technology Licensing, Llc. Data visualization extensibility architecture
US10102664B1 (en) * 2014-12-03 2018-10-16 Charles Schwab & Co., Inc. System and method for causing graphical information to be rendered
US9767122B2 (en) 2015-01-27 2017-09-19 Splunk Inc. Efficient point-in-polygon indexing technique to facilitate displaying geographic data
US9607414B2 (en) * 2015-01-27 2017-03-28 Splunk Inc. Three-dimensional point-in-polygon operation to facilitate displaying three-dimensional structures
US9916326B2 (en) 2015-01-27 2018-03-13 Splunk, Inc. Efficient point-in-polygon indexing technique for facilitating geofencing operations
US9836874B2 (en) * 2015-01-27 2017-12-05 Splunk Inc. Efficient polygon-clipping technique to reduce data transfer requirements for a viewport
US10026204B2 (en) 2015-01-27 2018-07-17 Splunk Inc. Efficient point-in-polygon indexing technique for processing queries over geographic data sets
US9733823B2 (en) 2015-04-01 2017-08-15 Microsoft Technology Licensing, Llc View activation via hit testing in an asynchronous windowing system
US9786081B1 (en) * 2015-05-14 2017-10-10 Domo, Inc. Transitioning between visual representations
US10037592B2 (en) 2015-06-05 2018-07-31 Mindaptiv LLC Digital quaternion logarithm signal processing system and method for images and other data types
US11373272B2 (en) 2015-06-05 2022-06-28 MindAptiv, LLC Digital gradient signal processing system and method for signals comprising at least three dimensions
US10672417B2 (en) * 2015-10-29 2020-06-02 True Image Interactive, Inc. Systems and methods for machine-generated avatars
KR102077146B1 (ko) * 2016-03-15 2020-02-13 (주)넥셀 그래픽 처리 방법 및 장치
US9733999B1 (en) 2016-03-24 2017-08-15 Wells Fargo Bank, N.A. Dynamic optimization of application workflows
WO2017213234A1 (en) * 2016-06-10 2017-12-14 Sharp Kabushiki Kaisha Systems and methods for signaling of information associated with a visual language presentation
WO2019037558A1 (zh) 2017-08-22 2019-02-28 优酷网络技术(北京)有限公司 图像处理方法和装置
WO2019046323A1 (en) 2017-08-28 2019-03-07 Oxide Interactive, LLC LAMINATE, SPACE, PROGRAMMABLE AND ASYNCHRONOUS SURFACE GENERATION SYSTEM
EP4002285A1 (en) * 2017-10-13 2022-05-25 Dassault Systèmes Method for creating an animation summarizing a design process of a three-dimensional object
US11417044B2 (en) * 2018-05-20 2022-08-16 Thomas Charley Long Advanced delay analysis mechanism
US11880422B2 (en) 2019-02-04 2024-01-23 Cloudflare, Inc. Theft prevention for sensitive information
US10558824B1 (en) 2019-02-04 2020-02-11 S2 Systems Corporation Application remoting using network vector rendering
US10552639B1 (en) 2019-02-04 2020-02-04 S2 Systems Corporation Local isolator application with cohesive application-isolation interface
US10452868B1 (en) 2019-02-04 2019-10-22 S2 Systems Corporation Web browser remoting using network vector rendering
CN112348748A (zh) * 2019-08-09 2021-02-09 北京字节跳动网络技术有限公司 图像特效处理方法、装置、电子设备和计算机可读存储介质
US11488338B2 (en) * 2020-04-17 2022-11-01 Raytheon Company Efficient three-dimensional, interactive image rendering
US20220134222A1 (en) * 2020-11-03 2022-05-05 Nvidia Corporation Delta propagation in cloud-centric platforms for collaboration and connectivity
CN112597266A (zh) * 2020-12-16 2021-04-02 深圳中清龙图网络技术有限公司 用于处理游戏模板数据的编辑器生成方法和处理方法
CN113192211B (zh) * 2021-03-23 2023-04-07 北京师范大学 一种基于3d模型的唐三彩虚拟上色系统及方法

Family Cites Families (86)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US4209852A (en) * 1974-11-11 1980-06-24 Hyatt Gilbert P Signal processing and memory arrangement
AU647086B2 (en) 1990-01-30 1994-03-17 Johnson Service Company Networked facilities management system
US5509115A (en) 1990-08-08 1996-04-16 Peerless Systems Corporation Method and apparatus for displaying a page with graphics information on a continuous synchronous raster output device
US5261041A (en) * 1990-12-28 1993-11-09 Apple Computer, Inc. Computer controlled animation system based on definitional animated objects and methods of manipulating same
US5852449A (en) * 1992-01-27 1998-12-22 Scientific And Engineering Software Apparatus for and method of displaying running of modeled system designs
AU4279893A (en) 1992-04-10 1993-11-18 Avid Technology, Inc. A method and apparatus for representing and editing multimedia compositions
US5987627A (en) 1992-05-13 1999-11-16 Rawlings, Iii; Joseph H. Methods and apparatus for high-speed mass storage access in a computer system
US5500933A (en) * 1993-04-28 1996-03-19 Canon Information Systems, Inc. Display system which displays motion video objects combined with other visual objects
EP0695446B1 (en) * 1993-05-10 1997-09-03 Taligent, Inc. Multimedia synchronization system
US5555368A (en) * 1993-12-30 1996-09-10 Taligent Object-oriented multi-tasking view framework
US5912666A (en) * 1994-08-23 1999-06-15 Object Technology Licensing Corp. Object-oriented global cursor tool
US5745761A (en) 1994-12-15 1998-04-28 International Business Machines Corporation Advanced graphics driver architecture with extension capability
US5986667A (en) * 1994-12-22 1999-11-16 Apple Computer, Inc. Mechanism for rendering scenes using an object drawing subsystem
US5732198A (en) 1995-02-09 1998-03-24 Oki America, Inc. Host based printing system for printing a document having at least one page
US5727141A (en) 1995-05-05 1998-03-10 Apple Computer, Inc. Method and apparatus for identifying user-selectable regions within multiple display frames
US5790130A (en) 1995-06-08 1998-08-04 Hewlett-Packard Company Texel cache interrupt daemon for virtual memory management of texture maps
US5930810A (en) * 1995-08-09 1999-07-27 Taylor Corporation Printing system with pre-defined user modifiable forms and local and remote printing
US5986675A (en) * 1996-05-24 1999-11-16 Microsoft Corporation System and method for animating an object in three-dimensional space using a two-dimensional input device
US5936632A (en) 1996-07-26 1999-08-10 Hewlett-Packard Co. Method for fast downloading of textures to accelerated graphics hardware and the elimination of extra software copies of texels
US6275857B1 (en) * 1996-10-30 2001-08-14 Microsoft Corporation System and method for freeing shared resources in a computer system
US5920325A (en) * 1996-11-20 1999-07-06 International Business Machines Corporation Prioritization of background display during animation
US6137499A (en) * 1997-03-07 2000-10-24 Silicon Graphics, Inc. Method, system, and computer program product for visualizing data using partial hierarchies
US6195694B1 (en) * 1997-03-13 2001-02-27 International Business Machines Corporation Server for reconfiguring control of a subset of devices on one or more kiosks
US6160907A (en) 1997-04-07 2000-12-12 Synapix, Inc. Iterative three-dimensional process for creating finished media content
WO1998046006A2 (en) * 1997-04-07 1998-10-15 At & T Corp. System and method for interfacing mpeg-coded audiovisual objects permitting adaptive control
US6215495B1 (en) * 1997-05-30 2001-04-10 Silicon Graphics, Inc. Platform independent application program interface for interactive 3D scene management
US5924098A (en) 1997-06-30 1999-07-13 Sun Microsystems, Inc. Method and apparatus for managing a linked-list data structure
US6377263B1 (en) * 1997-07-07 2002-04-23 Aesthetic Solutions Intelligent software components for virtual worlds
US6314470B1 (en) * 1997-07-25 2001-11-06 Hewlett Packard Company System and method for asynchronously accessing a graphics system for graphics application evaluation and control
US6154215A (en) * 1997-08-01 2000-11-28 Silicon Graphics, Inc. Method and apparatus for maintaining multiple representations of a same scene in computer generated graphics
US6654931B1 (en) 1998-01-27 2003-11-25 At&T Corp. Systems and methods for playing, browsing and interacting with MPEG-4 coded audio-visual objects
US6243856B1 (en) * 1998-02-03 2001-06-05 Amazing Media, Inc. System and method for encoding a scene graph
US6272650B1 (en) * 1998-02-03 2001-08-07 Amazing Media, Inc. System and method for disambiguating scene graph loads
US6075532A (en) * 1998-03-23 2000-06-13 Microsoft Corporation Efficient redrawing of animated windows
US6266053B1 (en) * 1998-04-03 2001-07-24 Synapix, Inc. Time inheritance scene graph for representation of media content
US6570578B1 (en) 1998-04-03 2003-05-27 Avid Technology, Inc. System for automatic generation of selective partial renderings of complex scenes
US6237092B1 (en) * 1998-05-05 2001-05-22 International Business Machines Corp. Client-server system with central application management allowing an administrator to configure user and group contexts during application configuration without relaunching the application
US6631403B1 (en) 1998-05-11 2003-10-07 At&T Corp. Architecture and application programming interfaces for Java-enabled MPEG-4 (MPEG-J) systems
JP2002519954A (ja) * 1998-06-26 2002-07-02 ジェネラル・インスツルメント・コーポレイション Mpeg−4ビデオプログラムを構成しかつ提示するためのターミナル
US6731314B1 (en) * 1998-08-17 2004-05-04 Muse Corporation Network-based three-dimensional multiple-user shared environment apparatus and method
US6487565B1 (en) * 1998-12-29 2002-11-26 Microsoft Corporation Updating animated images represented by scene graphs
US6411297B1 (en) * 1999-03-03 2002-06-25 Discreet Logic Inc. Generating image data
US6714201B1 (en) * 1999-04-14 2004-03-30 3D Open Motion, Llc Apparatuses, methods, computer programming, and propagated signals for modeling motion in computer applications
US6986101B2 (en) * 1999-05-06 2006-01-10 International Business Machines Corporation Method and apparatus for converting programs and source code files written in a programming language to equivalent markup language files
US6707456B1 (en) * 1999-08-03 2004-03-16 Sony Corporation Declarative markup for scoring multiple time-based assets and events within a scene composition system
US7184038B2 (en) * 1999-09-24 2007-02-27 Sun Microsystems, Inc. Using render bin parallelism for rendering scene graph based graphics data
US6765571B2 (en) * 1999-09-24 2004-07-20 Sun Microsystems, Inc. Using a master controller to manage threads and resources for scene-based rendering
US6538656B1 (en) * 1999-11-09 2003-03-25 Broadcom Corporation Video and graphics system with a data transport processor
WO2001040933A2 (en) * 1999-12-06 2001-06-07 Axiomatic Design Software, Inc. Method and apparatus for producing software using axiomatic design
US7102651B1 (en) * 1999-12-22 2006-09-05 Adobe Systems Incorporated Hierarchical 2-D color compositing with blending mode and opacity controls at all levels
US7103581B1 (en) 2000-01-13 2006-09-05 Hewlett-Packard Development Company, L.P. System and method for pricing print jobs
US6833840B2 (en) 2000-02-14 2004-12-21 Optibase Ltd PROTO implementation in MPEG-4
JP2001273520A (ja) * 2000-03-23 2001-10-05 Famotik Ltd マルチメディアドキュメント統合表示システム
US6751655B1 (en) * 2000-04-18 2004-06-15 Sun Microsystems, Inc. Method and apparatus for transport of scenegraph information across a network
US6717599B1 (en) * 2000-06-29 2004-04-06 Microsoft Corporation Method, system, and computer program product for implementing derivative operators with graphics hardware
US20020019844A1 (en) 2000-07-06 2002-02-14 Kurowski Scott J. Method and system for network-distributed computing
WO2002013002A2 (en) * 2000-08-04 2002-02-14 Intrinsic Graphics, Inc. Development of graphics hardware and software
US6675230B1 (en) * 2000-08-22 2004-01-06 International Business Machines Corporation Method, system, and program for embedding a user interface object in another user interface object
US7143339B2 (en) * 2000-09-20 2006-11-28 Sap Aktiengesellschaft Method and apparatus for dynamically formatting and displaying tabular data in real time
US6732109B2 (en) * 2001-01-31 2004-05-04 The Eon Company Method and system for transferring information between a user interface and a database over a global information network
FR2823942A1 (fr) * 2001-04-24 2002-10-25 Koninkl Philips Electronics Nv Dispositif pour une conversion d'un format bifs textuel vers un format bifs binaire
US7069503B2 (en) * 2001-06-04 2006-06-27 Murata Kikai Kabushiki Kaisha Device and program for structured document generation data structure of structural document
US7305011B2 (en) * 2001-06-14 2007-12-04 International Business Machines Corporation Periodic broadcast and location of evolving media content with application to seminar and stroke media
US7161599B2 (en) * 2001-10-18 2007-01-09 Microsoft Corporation Multiple-level graphics processing system and method
US7064766B2 (en) * 2001-10-18 2006-06-20 Microsoft Corporation Intelligent caching data structure for immediate mode graphics
US6919891B2 (en) * 2001-10-18 2005-07-19 Microsoft Corporation Generic parameterization for a scene graph
CA2465104A1 (en) 2001-10-23 2003-05-01 Samsung Electronics Co., Ltd. Information storage medium including markup document and av data, recording method, reproducing method, and reproducing apparatus therefor
US6626211B2 (en) 2001-11-27 2003-09-30 Toyoda Gosei Co., Ltd. Brake hose
US7055092B2 (en) * 2001-12-05 2006-05-30 Canon Kabushiki Kaisha Directory for multi-page SVG document
US20030110297A1 (en) * 2001-12-12 2003-06-12 Tabatabai Ali J. Transforming multimedia data for delivery to multiple heterogeneous devices
US20040110490A1 (en) * 2001-12-20 2004-06-10 Steele Jay D. Method and apparatus for providing content to media devices
KR100453225B1 (ko) * 2001-12-26 2004-10-15 한국전자통신연구원 3차원 가상 현실 구현을 위한 클라이언트 시스템과 이를이용한 가상 현실 구현 방법
US7076332B2 (en) * 2002-01-18 2006-07-11 National Instruments Corporation System and method for invoking execution of a sequence of operations that includes motion control, machine vision, and data acquisition (DAQ) functionality
EP1472620A2 (en) * 2002-02-04 2004-11-03 Mobileaware Technologies Limited Document transformation
US20030210267A1 (en) 2002-05-13 2003-11-13 Kylberg Robert Lee Systems and methods for providing asynchronous client rendering in a graphical user interface (GUI) environment
AU2003249168A1 (en) * 2002-07-11 2004-02-02 Raytheon Company System and method for asynchronous storage and playback of a system state
WO2004008303A2 (en) * 2002-07-12 2004-01-22 Raytheon Company Scene graph based display for desktop applications
US20040216139A1 (en) * 2002-08-21 2004-10-28 Rhoda Merlin A. System controlling test/measurement devices on a network using markup language documents and methods thereof
US7240346B2 (en) * 2002-11-13 2007-07-03 Microsoft Corporation Method and system for accessing drawing resources
US7126606B2 (en) * 2003-03-27 2006-10-24 Microsoft Corporation Visual and scene graph interfaces
US7088374B2 (en) * 2003-03-27 2006-08-08 Microsoft Corporation System and method for managing visual structure, timing, and animation in a graphics processing system
US7466315B2 (en) * 2003-03-27 2008-12-16 Microsoft Corporation Visual and scene graph interfaces
US7486294B2 (en) * 2003-03-27 2009-02-03 Microsoft Corporation Vector graphics element-based model, application programming interface, and markup language
US7412455B2 (en) * 2003-04-30 2008-08-12 Dillon David M Software framework that facilitates design and implementation of database applications
US8051389B2 (en) * 2003-08-26 2011-11-01 Hewlett-Packard Development Company, L.P. Methods of displaying resources of overlapping but separate hierarchies
US7012606B2 (en) * 2003-10-23 2006-03-14 Microsoft Corporation System and method for a unified composition engine in a graphics processing system

Cited By (10)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN101986307A (zh) * 2010-11-11 2011-03-16 东莞宇龙通信科技有限公司 一种mime类型插件的生成方法、系统及浏览器
CN103198471A (zh) * 2013-02-28 2013-07-10 天脉聚源(北京)传媒科技有限公司 一种视频的裁切方法及装置
TWI786321B (zh) * 2014-10-06 2022-12-11 美商Vid衡器股份有限公司 用於解碼/編碼的方法及裝置、計算機程式產品、計算機程式及視訊資料
US11558627B2 (en) 2014-10-06 2023-01-17 Vid Scale, Inc. Palette coding for screen content coding
CN106658145A (zh) * 2016-12-27 2017-05-10 北京奇虎科技有限公司 一种直播数据处理方法和装置
CN106658145B (zh) * 2016-12-27 2020-07-03 北京奇虎科技有限公司 一种直播数据处理方法和装置
CN110297657A (zh) * 2019-06-11 2019-10-01 东南大学 一种基于层次上下文的api推荐方法
CN110764757A (zh) * 2019-10-22 2020-02-07 成都九洲电子信息系统股份有限公司 一种基于html5的交互式图形绘制引擎
CN113326031A (zh) * 2021-05-28 2021-08-31 网易(杭州)网络有限公司 属性获取方法和装置
CN113326031B (zh) * 2021-05-28 2023-08-22 网易(杭州)网络有限公司 属性获取方法和装置

Also Published As

Publication number Publication date
NO20052269L (no) 2005-11-24
WO2005045584A3 (en) 2005-12-15
BRPI0406378A (pt) 2005-08-09
EP1623406A4 (en) 2009-11-11
ZA200503159B (en) 2006-10-25
NO20052269D0 (no) 2005-05-10
NZ540116A (en) 2007-09-28
RU2005120391A (ru) 2006-01-20
CA2501452A1 (en) 2005-04-23
RU2360275C2 (ru) 2009-06-27
EP1623406A2 (en) 2006-02-08
KR20070028202A (ko) 2007-03-12
WO2005045584A2 (en) 2005-05-19
AU2004279199A1 (en) 2005-06-23
US20050140694A1 (en) 2005-06-30
JP2007509426A (ja) 2007-04-12
TW200515304A (en) 2005-05-01
AU2004279199A8 (en) 2008-10-02
US7511718B2 (en) 2009-03-31

Similar Documents

Publication Publication Date Title
CN1989543A (zh) 媒体集成层
CN101421761B (zh) 视件和场景图接口
US7486294B2 (en) Vector graphics element-based model, application programming interface, and markup language
RU2324229C2 (ru) Визуальный и пространственный графические интерфейсы
CN100533381C (zh) 用于在计算机系统上进行显示的系统和方法
Schechter et al. Functional 3D graphics in C++—with an object-oriented, multiple dispatching implementation
Yang Implementation of 3D graphic editor

Legal Events

Date Code Title Description
C06 Publication
PB01 Publication
C10 Entry into substantive examination
SE01 Entry into force of request for substantive examination
C02 Deemed withdrawal of patent application after publication (patent law 2001)
WD01 Invention patent application deemed withdrawn after publication

Open date: 20070627