summaryrefslogtreecommitdiff
path: root/html/en/internal.html
blob: cd72a188c78a136bff9bb2112f2b0b9b653c9093 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
<html>

<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<title>Internal Architecture</title>
<link rel="stylesheet" type="text/css" href="../style.css">
</head>

<body>

<h2>Internal Architecture</h2>

<h3>Modularity</h3>


  <p>Apart from the several drivers, the CD library is composed of a few modules, the public
  header files <b>cd.h</b> and <b>wd.h</b>, those which implement the functions
  independently from drivers,<b> cd*.c</b> and <b>wd.c</b>, and the header file <b>cd_private.h</b>,
  apart from some other modules which implement non-exported specific functions. Such
  modules are totally independent from the implemented drivers, as well as every driver
  independs from one another, unless there is an intentional dependency.</p>


<h3>Linking</h3>


  <p>Since the drivers independ from one another, we could create a library for each of
  them. For the drivers provided with CD it was easy to include them in their own library,
  thus simplifying the application's linking process. Note: Internally, the drivers are
  called &quot;context&quot;.</p>
  <p>In order to establish this dependency, when creating a canvas in a given driver the
  user must specify the driver to be used. This specification is done by means of a macro
  which is actually a function with no parameter, which passes the function table from that
  driver to the canvas creation function. For instance:</p>
  
    <pre><b>CD_PS</b> <em>(is in fact)</em> cdContextPS()
cdCreateCanvas(<b>CD_PS</b>, &quot;teste.ps&quot;); <em>(will do)</em> canvas-&gt;<b>Line</b> = context-&gt;<b>Line</b></pre>
<p>If the context function is not invoqued then that driver does not need to be 
linked with the application. This is usefull if the application uses a custom 
build of the CD library and usefull for additional drivers not included in the 
main library, like IUP and PDF, that have external dependencies.</p>
  


<h3>Structures</h3>


  <p>The core implementation defines the structures declared in the cd.h header. 
  But declares an undefined structure called cdCtxCanvas. This structure is 
  defined in each driver according to their needs. But the first member of this 
  structure must be a pointer to the cdCanvas structure.</p>
  <p>The drivers need not to implement all functions from the function table, 
  only a few are required.</p>
  <p>Here is the definition of the cdContext and cdCanvas structures:&nbsp; </p>
  <table BORDER="1" CELLPADDING="5">
    <tr>
      <td><pre>struct <b>_cdContext
</b>{
  unsigned long caps;

  /* can NOT be NULL */
  void (*CreateCanvas)(cdCanvas* canvas, void *data);
  void (*InitTable)(cdCanvas* canvas);

  /* can be NULL */
  int (*Play)(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data); 
  int (*RegisterCallback)(int cb, cdCallback func);
};</pre>
      </td>
    </tr>
    <tr>
      <td><pre>struct <b>_cdCanvas
</b>{
&nbsp; ...
&nbsp; void (*Line)(cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2);
&nbsp; void (*Rect)(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax);
&nbsp; void (*Box)(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax);
&nbsp; ...

&nbsp; ...
&nbsp; int mark_type, mark_size;
&nbsp; int line_style, line_width;
&nbsp; int interior_style, hatch_style;
&nbsp; ...

  cdVectorFont* vector_font;
  cdSimulation* simulation;
  cdCtxCanvas* ctxcanvas;     // context dependent defintion
  cdContext* context;
};</pre>
      </td>
    </tr>
  </table>



  <p>Internally each driver defines its cdCtxCanvas strcuture:</p>
<pre>struct _cdCtxCanvas 
{
  cdCanvas* canvas;

  char* filename; 

  int last_line_style;
  int last_fill_mode;
  FILE* file;
};</pre>
<p>Then it must implement the cdcreatecanvas and cdinittable functions:</p>
<pre>/* In the driver implementation file */

static void cdcreatecanvas(cdCanvas *canvas, void *data)
{
  cdCtxCanvas* ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas));

  // parse data parameters
  ...

  ctxcanvas-&gt;canvas = canvas;
  canvas-&gt;ctxcanvas = ctxcanvas;

  /* update canvas context */
  canvas-&gt;w = (int)(w_mm * res);
  canvas-&gt;h = (int)(h_mm * res);
  canvas-&gt;w_mm = w_mm;
  canvas-&gt;h_mm = h_mm;
  canvas-&gt;bpp = 24;
  canvas-&gt;xres = res;
  canvas-&gt;yres = res;
}

static void cdinittable(cdCanvas* canvas)
{
  canvas-&gt;Flush = cdflush;
  canvas-&gt;Clear = cdclear;
  canvas-&gt;Pixel = cdpixel;
  canvas-&gt;Line = cdline;
  canvas-&gt;Poly = cdpoly;
  ...
 }

static cdContext cdMetafileContext =
{
  CD_CAP_ALL &amp; ~(CD_CAP_GETIMAGERGB|CD_CAP_IMAGESRV|CD_CAP_REGION|CD_CAP_FONTDIM|CD_CAP_TEXTSIZE),
  cdcreatecanvas,
  cdinittable,
  cdplay,
  cdregistercallback,
};

cdContext* cdContextMetafile(void)
{
  return &amp;cdMetafileContext;
}</pre>
<p>To simplify driver administration, the context structure's linking is done as follows:</p>
  
    <pre>/* In the header file */
#define <b>CD_METAFILE</b> <b><i>cdContextMetafile()
</i>cdContext</b>* <b><i>cdContextMetafile</i></b>(void)
</pre>
  



<h3>Attributes</h3>


  <p>The query mechanism of an attribute is done in the core and does not
  depends on the driver. Due to this fact, the attributes which are modified several times for the same
  value are not updated in the drivers, thus saving processing. Similarly, if an attribute
  modification in a driver was not successful, its value is not updated. Nevertheless, the
  fact that a driver does not implement the attribute's modification function does not mean
  that it rejects that attribute - the driver just does not need to do anything with this
  attribute on that moment and will query it later, before drawing the primitive.</p>
  <p>The creation of customized attributes for each driver is made generically, using
  string-like attributes. A structure with the attribute's name and its <em>set</em> and <em>get</em>
  functions must be declared, as in the example below:</p>
  
    <pre>static void set_fill_attrib(cdCtxCanvas* ctxcanvas, char* data)
{
  ctxcanvas-&gt;fill_attrib[0] = data[0];
}

static char* get_fill_attrib(cdCtxCanvas* ctxcanvas)
{
  return ctxcanvas-&gt;fill_attrib;
}

static cdAttribute fill_attrib =
{
  &quot;SIMPENFILLPOLY&quot;,
  set_fill_attrib,
  get_fill_attrib
}; </pre>
  
  <p>At <em>createcanvas</em> in the driver: </p>
  
    <pre>ctxcanvas-&gt;fill_attrib[0] = '1';
ctxcanvas-&gt;fill_attrib[1] = 0;

cdRegisterAttribute(canvas, &amp;fill_attrib);</pre>
  
  <p>, for instance, must exist, thus initializing the attribute and registering it in the
  canvas' attribute list.</p>


</body>
</html>