Решил попробовать свои силы в создании компонента с применением модели
Model-View-Controller, разбираясь в принципе работы библиотеки Cairo по её исходникам.
Абстрактная модель работает по приципу фабрики (абстракция-реализация), хотя и требует доработки. Зависимости от каркаса БлэкБокса нет, однако построена по тому же принципу. Есть Model, Writer, View, Directory. Можно даже добавить в будущем экспорт/импорт в/из модель/и с помощью Internalize, Externalize.
Сначала строится векторная модель, которая ничего не знает о целевой поверхности. Ею может быть векторный документ (PS, PDF, SVG), рисуемая поверхность (GDI+, Xlib, Quartz, ...) или буфер изображения в памяти. Как только модель построена, её можно отображать в любой вид Views.Surface: DocumentSurface, DrawableSurface, ImageSurface.
Реализация пока лишь частичная и испольуется всё та же библиотека Cairo. В дальнейшем планируется отвязаться от связки реализации с Cairo, переписав алгоритмы растеризации на Компонентный Паскаль. Правда, работы там - не хило.
Вот такая демка уже работает, пишет векторную модель в изображение PNG:
Код:
MODULE VgDemo;
IMPORT Types := VgTypes, Models := VgModels, StdModels := VgStdModels, Views := VgViews,
StdLog;
PROCEDURE Run*;
VAR
drawingModel: Models.Model;
pattern: StdModels.SolidPattern;
path: Models.Path;
surface: Views.Surface;
BEGIN
drawingModel := Models.dir.New(70, 50);
ASSERT(drawingModel # NIL, 20);
path := drawingModel.NewPathWriter(NIL);
ASSERT(path # NIL, 20);
path.MoveTo(50, 35, Types.ABSOLUTE);
path.LineTo(10, 15, Types.ABSOLUTE);
path.LineTo(20, 22, Types.ABSOLUTE);
path.CurveTo(0, 5, 12, 43, 32, 8, Types.ABSOLUTE);
path.ClosePath;
StdLog.String("Status: "); StdLog.Int(Types.status); StdLog.Ln;
(*
path.MoveTo(25, 43, Types.ABSOLUTE);
path.LineTo(-25, -43, Types.ABSOLUTE);
path.LineTo(-25, 43, Types.ABSOLUTE);
path.CurveTo(20, -15, 45, -31, -2, 8, Types.ABSOLUTE);
path.ClosePath;
StdLog.String("Status: "); StdLog.Int(Types.status); StdLog.Ln;
*)
pattern := StdModels.NewSolidPattern() (StdModels.SolidPattern);
ASSERT(pattern # NIL, 21);
pattern.SetColorRGB(0.8, 0.6, 0.24);
drawingModel.SetLineWidth(0.2);
drawingModel.SetSource(pattern);
surface := Views.dir.New(drawingModel);
ASSERT(surface # NIL, 21);
surface.Fill;
surface.Destroy;
drawingModel.Destroy
END Run;
END VgDemo.