1 // Copyright (c) 1996 James Clark
2 // See the file copying.txt for copying permission.
3
4 #include "stylelib.h"
5 #include "Style.h"
6 #include "VM.h"
7 #include "Interpreter.h"
8 #include "InterpreterMessages.h"
9 #include "SosofoObj.h"
10 #include "macros.h"
11
12 #ifdef DSSSL_NAMESPACE
13 namespace DSSSL_NAMESPACE {
14 #endif
15
StyleStack()16 StyleStack::StyleStack()
17 : level_(0)
18 {
19 }
20
pushContinue(StyleObj * style,const ProcessingMode::Rule * rule,const NodePtr & nodePtr,Messenger * mgr)21 void StyleStack::pushContinue(StyleObj *style,
22 const ProcessingMode::Rule *rule,
23 const NodePtr &nodePtr,
24 Messenger *mgr)
25 {
26 StyleObjIter iter;
27 style->appendIter(iter);
28 for (;;) {
29 const VarStyleObj *varStyle;
30 ConstPtr<InheritedC> spec(iter.next(varStyle));
31 if (spec.isNull())
32 break;
33 size_t ind = spec->index();
34 if (ind >= inheritedCInfo_.size())
35 inheritedCInfo_.resize(ind + 1);
36 Ptr<InheritedCInfo> &info = inheritedCInfo_[ind];
37 if (!info.isNull() && info->valLevel == level_) {
38 if (rule) {
39 ASSERT(info->rule != 0);
40 if (rule->compareSpecificity(*info->rule) == 0) {
41 mgr->setNextLocation(info->rule->location());
42 mgr->message(InterpreterMessages::ambiguousStyle,
43 StringMessageArg(info->spec->identifier()->name()),
44 rule->location());
45 }
46 }
47
48 }
49 else {
50 popList_->list.push_back(ind);
51 info = new InheritedCInfo(spec, varStyle, level_, level_, rule, info);
52 }
53 }
54 }
55
pushEnd(VM & vm,FOTBuilder & fotb)56 void StyleStack::pushEnd(VM &vm, FOTBuilder &fotb)
57 {
58 const PopList *oldPopList = popList_->prev.pointer();
59 if (oldPopList) {
60 for (size_t i = 0; i < oldPopList->dependingList.size(); i++) {
61 size_t d = oldPopList->dependingList[i];
62 // d is the index of a characteristic that depends on the actual
63 // value of another characteritistic
64 if (inheritedCInfo_[d]->valLevel != level_) {
65 const Vector<size_t> &dependencies = inheritedCInfo_[d]->dependencies;
66 bool changed = 0;
67 for (size_t j = 0; j < dependencies.size(); j++) {
68 const InheritedCInfo *p = inheritedCInfo_[dependencies[j]].pointer();
69 if (p && p->valLevel == level_) {
70 inheritedCInfo_[d] = new InheritedCInfo(inheritedCInfo_[d]->spec,
71 inheritedCInfo_[d]->style,
72 level_,
73 inheritedCInfo_[d]->specLevel,
74 inheritedCInfo_[d]->rule,
75 inheritedCInfo_[d]);
76 popList_->list.push_back(d);
77 changed = 1;
78 break;
79 }
80 }
81 // If it changed, then doing set() on the new value will add
82 // it to the dependingList for this level.
83 if (!changed)
84 popList_->dependingList.push_back(d);
85 }
86 }
87 }
88 vm.styleStack = this;
89 for (size_t i = 0; i < popList_->list.size(); i++) {
90 InheritedCInfo &info = *inheritedCInfo_[popList_->list[i]];
91 vm.specLevel = info.specLevel;
92 info.spec->set(vm, info.style, fotb, info.cachedValue, info.dependencies);
93 if (info.dependencies.size())
94 popList_->dependingList.push_back(popList_->list[i]);
95 }
96 vm.styleStack = 0;
97 }
98
pop()99 void StyleStack::pop()
100 {
101 for (size_t i = 0; i < popList_->list.size(); i++) {
102 size_t ind = popList_->list[i];
103 ASSERT(inheritedCInfo_[ind]->valLevel == level_);
104 Ptr<InheritedCInfo> tem(inheritedCInfo_[ind]->prev);
105 inheritedCInfo_[ind] = tem;
106 }
107 level_--;
108 Ptr<PopList> tem(popList_->prev);
109 popList_ = tem;
110 }
111
inherited(const ConstPtr<InheritedC> & ic,unsigned specLevel,Interpreter & interp,Vector<size_t> & dependencies)112 ELObj *StyleStack::inherited(const ConstPtr<InheritedC> &ic, unsigned specLevel,
113 Interpreter &interp, Vector<size_t> &dependencies)
114 {
115 ASSERT(specLevel != unsigned(-1));
116 size_t ind = ic->index();
117 ConstPtr<InheritedC> spec;
118 const VarStyleObj *style = 0;
119 unsigned newSpecLevel = unsigned(-1);
120 if (ind >= inheritedCInfo_.size())
121 spec = ic;
122 else {
123 const InheritedCInfo *p = inheritedCInfo_[ind].pointer();
124 while (p != 0) {
125 if (p->specLevel < specLevel)
126 break;
127 p = p->prev.pointer();
128 }
129 if (!p)
130 spec = ic;
131 else {
132 if (p->cachedValue) {
133 // We can only use the cached value if none of the values
134 // we depended on changed since we computed it.
135 bool cacheOk = 1;
136 for (size_t i = 0; i < p->dependencies.size(); i++) {
137 size_t d = p->dependencies[i];
138 if (d < inheritedCInfo_.size()
139 && inheritedCInfo_[d]->valLevel > p->valLevel) {
140 cacheOk = 0;
141 break;
142 }
143 }
144 if (cacheOk)
145 return p->cachedValue;
146 }
147 style = p->style;
148 spec = p->spec;
149 newSpecLevel = p->specLevel;
150 }
151 }
152 VM vm(interp);
153 vm.styleStack = this;
154 vm.specLevel = newSpecLevel;
155 return spec->value(vm, style, dependencies);
156 }
157
actual(const ConstPtr<InheritedC> & ic,const Location & loc,Interpreter & interp,Vector<size_t> & dependencies)158 ELObj *StyleStack::actual(const ConstPtr<InheritedC> &ic, const Location &loc,
159 Interpreter &interp, Vector<size_t> &dependencies)
160 {
161 size_t ind = ic->index();
162 for (size_t i = 0; i < dependencies.size(); i++) {
163 if (dependencies[i] == ind) {
164 interp.setNextLocation(loc);
165 interp.message(InterpreterMessages::actualLoop,
166 StringMessageArg(ic->identifier()->name()));
167 return interp.makeError();
168 }
169 }
170 dependencies.push_back(ind);
171 ConstPtr<InheritedC> spec;
172 const VarStyleObj *style = 0;
173 if (ind >= inheritedCInfo_.size())
174 spec = ic;
175 else {
176 const InheritedCInfo *p = inheritedCInfo_[ind].pointer();
177 if (!p)
178 spec = ic;
179 else if (p->cachedValue) {
180 const Vector<size_t> &dep = p->dependencies;
181 for (size_t i = 0; i < dep.size(); i++)
182 dependencies.push_back(dep[i]);
183 return p->cachedValue;
184 }
185 else {
186 style = p->style;
187 spec = p->spec;
188 }
189 }
190 VM vm(interp);
191 vm.styleStack = this;
192 vm.specLevel = level_;
193 return spec->value(vm, style, dependencies);
194 }
195
trace(Collector & c) const196 void StyleStack::trace(Collector &c) const
197 {
198 for (size_t i = 0; i < inheritedCInfo_.size(); i++) {
199 for (const InheritedCInfo *p = inheritedCInfo_[i].pointer();
200 p;
201 p = p->prev.pointer()) {
202 c.trace(p->style);
203 c.trace(p->cachedValue);
204 }
205 }
206 }
207
InheritedCInfo(const ConstPtr<InheritedC> & sp,const VarStyleObj * so,unsigned vl,unsigned sl,const ProcessingMode::Rule * r,const Ptr<InheritedCInfo> & p)208 InheritedCInfo::InheritedCInfo(const ConstPtr<InheritedC> &sp,
209 const VarStyleObj *so,
210 unsigned vl,
211 unsigned sl,
212 const ProcessingMode::Rule *r,
213 const Ptr<InheritedCInfo> &p)
214 : spec(sp), style(so), valLevel(vl), specLevel(sl), rule(r), prev(p), cachedValue(0)
215 {
216 }
217
asStyle()218 StyleObj *StyleObj::asStyle()
219 {
220 return this;
221 }
222
VarStyleObj(const ConstPtr<StyleSpec> & styleSpec,StyleObj * use,ELObj ** display,const NodePtr & node)223 VarStyleObj::VarStyleObj(const ConstPtr<StyleSpec> &styleSpec, StyleObj *use, ELObj **display,
224 const NodePtr &node)
225 : styleSpec_(styleSpec), use_(use), display_(display), node_(node)
226 {
227 hasSubObjects_ = 1;
228 }
229
~VarStyleObj()230 VarStyleObj::~VarStyleObj()
231 {
232 delete [] display_;
233 }
234
traceSubObjects(Collector & c) const235 void VarStyleObj::traceSubObjects(Collector &c) const
236 {
237 c.trace(use_);
238 if (display_)
239 for (ELObj **pp = display_; *pp; pp++)
240 c.trace(*pp);
241 }
242
appendIterForce(StyleObjIter & iter) const243 void VarStyleObj::appendIterForce(StyleObjIter &iter) const
244 {
245 if (styleSpec_->forceSpecs.size())
246 iter.append(&styleSpec_->forceSpecs, this);
247 }
248
appendIterNormal(StyleObjIter & iter) const249 void VarStyleObj::appendIterNormal(StyleObjIter &iter) const
250 {
251 if (styleSpec_->specs.size())
252 iter.append(&styleSpec_->specs, this);
253 if (use_)
254 use_->appendIter(iter);
255 }
256
appendIter(StyleObjIter & iter) const257 void VarStyleObj::appendIter(StyleObjIter &iter) const
258 {
259 VarStyleObj::appendIterForce(iter);
260 VarStyleObj::appendIterNormal(iter);
261 }
262
OverriddenStyleObj(BasicStyleObj * basic,StyleObj * override)263 OverriddenStyleObj::OverriddenStyleObj(BasicStyleObj *basic, StyleObj *override)
264 : basic_(basic), override_(override)
265 {
266 hasSubObjects_ = 1;
267 }
268
traceSubObjects(Collector & c) const269 void OverriddenStyleObj::traceSubObjects(Collector &c) const
270 {
271 c.trace(basic_);
272 c.trace(override_);
273 }
274
appendIter(StyleObjIter & iter) const275 void OverriddenStyleObj::appendIter(StyleObjIter &iter) const
276 {
277 basic_->appendIterForce(iter);
278 override_->appendIter(iter);
279 basic_->appendIterNormal(iter);
280 }
281
MergeStyleObj()282 MergeStyleObj::MergeStyleObj()
283 {
284 hasSubObjects_ = 1;
285 }
286
append(StyleObj * obj)287 void MergeStyleObj::append(StyleObj *obj)
288 {
289 styles_.push_back(obj);
290 }
291
appendIter(StyleObjIter & iter) const292 void MergeStyleObj::appendIter(StyleObjIter &iter) const
293 {
294 for (size_t i = 0; i < styles_.size(); i++)
295 styles_[i]->appendIter(iter);
296 }
297
traceSubObjects(Collector & c) const298 void MergeStyleObj::traceSubObjects(Collector &c) const
299 {
300 for (size_t i = 0; i < styles_.size(); i++)
301 c.trace(styles_[i]);
302 }
303
asColor()304 ColorObj *ColorObj::asColor()
305 {
306 return this;
307 }
308
DeviceRGBColorObj(unsigned char red,unsigned char green,unsigned char blue)309 DeviceRGBColorObj::DeviceRGBColorObj(unsigned char red, unsigned char green,
310 unsigned char blue)
311 {
312 color_.red = red;
313 color_.green = green;
314 color_.blue = blue;
315 }
316
set(FOTBuilder & fotb) const317 void DeviceRGBColorObj::set(FOTBuilder &fotb) const
318 {
319 fotb.setColor(color_);
320 }
321
setBackground(FOTBuilder & fotb) const322 void DeviceRGBColorObj::setBackground(FOTBuilder &fotb) const
323 {
324 fotb.setBackgroundColor(color_);
325 }
326
asColorSpace()327 ColorSpaceObj *ColorSpaceObj::asColorSpace()
328 {
329 return this;
330 }
331
makeColor(int argc,ELObj ** argv,Interpreter & interp,const Location & loc)332 ELObj *DeviceRGBColorSpaceObj::makeColor(int argc, ELObj **argv,
333 Interpreter &interp, const Location &loc)
334 {
335 if (argc == 0)
336 return new (interp) DeviceRGBColorObj(0, 0, 0);
337 if (argc != 3) {
338 interp.setNextLocation(loc);
339 interp.message(InterpreterMessages::RGBColorArgCount);
340 return interp.makeError();
341 }
342 unsigned char c[3];
343 for (int i = 0; i < 3; i++) {
344 double d;
345 if (!argv[i]->realValue(d)) {
346 interp.setNextLocation(loc);
347 interp.message(InterpreterMessages::RGBColorArgType);
348 return interp.makeError();
349 }
350 if (d < 0.0 || d > 1.0) {
351 interp.setNextLocation(loc);
352 interp.message(InterpreterMessages::RGBColorArgRange);
353 return interp.makeError();
354 }
355 c[i] = (unsigned char)(d*255.0 + .5);
356 }
357 return new (interp) DeviceRGBColorObj(c[0], c[1], c[2]);
358 }
359
VarInheritedC(const ConstPtr<InheritedC> & ic,const InsnPtr & code,const Location & loc)360 VarInheritedC::VarInheritedC(const ConstPtr<InheritedC> &ic,
361 const InsnPtr &code, const Location &loc)
362 : InheritedC(ic->identifier(), ic->index()), inheritedC_(ic), code_(code), loc_(loc)
363 {
364 }
365
set(VM & vm,const VarStyleObj * style,FOTBuilder & fotb,ELObj * & cacheObj,Vector<size_t> & dependencies) const366 void VarInheritedC::set(VM &vm, const VarStyleObj *style, FOTBuilder &fotb,
367 ELObj *&cacheObj, Vector<size_t> &dependencies) const
368 {
369 if (!cacheObj) {
370 EvalContext::CurrentNodeSetter cns(style->node(), 0, vm);
371 vm.actualDependencies = &dependencies;
372 cacheObj = vm.eval(code_.pointer(), style->display());
373 ASSERT(cacheObj != 0);
374 vm.actualDependencies = 0;
375 }
376 if (!vm.interp->isError(cacheObj)) {
377 ConstPtr<InheritedC> c(inheritedC_->make(cacheObj, loc_, *vm.interp));
378 if (!c.isNull())
379 c->set(vm, 0, fotb, cacheObj, dependencies);
380 }
381 }
382
make(ELObj * obj,const Location & loc,Interpreter & interp) const383 ConstPtr<InheritedC> VarInheritedC::make(ELObj *obj, const Location &loc, Interpreter &interp)
384 const
385 {
386 return inheritedC_->make(obj, loc, interp);
387 }
388
value(VM & vm,const VarStyleObj * style,Vector<size_t> & dependencies) const389 ELObj *VarInheritedC::value(VM &vm, const VarStyleObj *style,
390 Vector<size_t> &dependencies) const
391 {
392 EvalContext::CurrentNodeSetter cns(style->node(), 0, vm);
393 vm.actualDependencies = &dependencies;
394 return vm.eval(code_.pointer(), style->display());
395 }
396
StyleObjIter()397 StyleObjIter::StyleObjIter()
398 : i_(0), vi_(0)
399 {
400 }
401
append(const Vector<ConstPtr<InheritedC>> * v,const VarStyleObj * obj)402 void StyleObjIter::append(const Vector<ConstPtr<InheritedC> > *v, const VarStyleObj *obj)
403 {
404 styleVec_.push_back(obj);
405 vecs_.push_back(v);
406 }
407
next(const VarStyleObj * & style)408 ConstPtr<InheritedC> StyleObjIter::next(const VarStyleObj *&style)
409 {
410 for (; vi_ < vecs_.size(); vi_++, i_ = 0) {
411 if (i_ < vecs_[vi_]->size()) {
412 style = styleVec_[vi_];
413 return (*vecs_[vi_])[i_++];
414 }
415 }
416 return ConstPtr<InheritedC>();
417 }
418
StyleSpec(Vector<ConstPtr<InheritedC>> & fs,Vector<ConstPtr<InheritedC>> & s)419 StyleSpec::StyleSpec(Vector<ConstPtr<InheritedC> > &fs, Vector<ConstPtr<InheritedC> > &s)
420 {
421 fs.swap(forceSpecs);
422 s.swap(specs);
423 }
424
425 #ifdef DSSSL_NAMESPACE
426 }
427 #endif
428
429