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