00001 #ifndef hpp_CSSUnit_hpp
00002 #define hpp_CSSUnit_hpp
00003
00004
00005 #include "../Types/Types.hpp"
00006
00007 namespace CSS
00008 {
00010 struct BorderStyle
00011 {
00012 enum Style
00013 {
00014 None = 1,
00015 Hidden = 2,
00016 Dotted = 3,
00017 Dashed = 4,
00018 Solid = 5,
00019 Double = 6,
00020 Groove = 7,
00021 Ridge = 8,
00022 Inset = 9,
00023 Outset = 10,
00024 };
00025 };
00026
00028 struct Position
00029 {
00031 enum Type
00032 {
00033 Static = 0,
00034 Relative = 1,
00035 Absolute = 2,
00036 Fixed = 3,
00037 };
00038 };
00039
00043 struct DisplayMode
00044 {
00045 enum Type
00046 {
00047 Inline = 0,
00048 Block = 1,
00049 ListItem = 2,
00050 RunIn = 3,
00051 Compact = 4,
00052 Marker = 5,
00053 Table = 6,
00054 InlineTable = 7,
00055 TableRowGroup = 8,
00056 TableHeaderGroup= 9,
00057 TableFooterGroup= 10,
00058 TableRow = 11,
00059 TableColumnGroup= 12,
00060 TableColumn = 13,
00061 TableCell = 14,
00062 TableCaption = 15,
00063 None = 16
00064 };
00065 };
00066
00068 struct ClearAndFloat
00069 {
00070 enum Property
00071 {
00072 None = 0,
00073 Left = 1,
00074 Right = 2,
00075 Both = 3,
00076 };
00077 };
00078
00080 struct TextAlign
00081 {
00082 enum Type
00083 {
00084 Left = 1,
00085 Right = 2,
00086 Center = 3,
00087 Justify = 4,
00088 String = 5,
00089 } type;
00090
00092 TextAlign(const Type _type) : type(_type) {}
00093 };
00094
00097 struct StringAlignedText : public TextAlign
00098 {
00100 char* split;
00101 };
00102
00104 struct VerticalAlign
00105 {
00106 enum Type
00107 {
00108 Baseline = 0,
00109 Middle = 1,
00110 Sub = 2,
00111 Super = 3,
00112 TextTop = 4,
00113 TextBottom = 5,
00114 Top = 6,
00115 Bottom = 7,
00116 Number = 8,
00117 } type;
00118
00120 VerticalAlign(const Type _type) : type(_type) {}
00121 };
00122
00124 struct TextDecoration
00125 {
00126 enum Type
00127 {
00128 None = 0,
00129 Underline = 1,
00130 Overline = 2,
00131 LineThrough = 3,
00132 Blink = 4,
00133 };
00134 };
00135
00137 struct Length
00138 {
00139 protected:
00141 float value;
00143 mutable int32 computedValue;
00145 mutable uint32 iteration;
00147 Length(const float _value) : value(_value), computedValue(0x80000000), iteration(0) {}
00148
00149 public:
00151 virtual void setComputedValue(const int32 _value, const uint32 _iter) { computedValue = _value; iteration = _iter; }
00153 virtual const int32 getComputedValue() const { return computedValue; }
00154
00157 virtual int32 getAsPixels(const uint32 currentIteration = 0) const { return 0; }
00159 virtual void setZero() { value = 0; }
00161 virtual bool isAuto() const { return false; }
00163 virtual bool isAbsolute() const { return false; }
00164
00166 inline void setValue(const float val) { value = val; }
00167 };
00168
00171 struct SpecifiedVerticalAlign : public VerticalAlign
00172 {
00174 Length * value;
00176 SpecifiedVerticalAlign(Length * _value) : VerticalAlign(VerticalAlign::Number), value(_value) {}
00177 };
00178
00180 struct AutoLength : public Length
00181 {
00182 public:
00184 AutoLength() : Length(0) {}
00186 AutoLength(const AutoLength & other) : Length(other.value) {}
00187
00188
00189 public:
00191 virtual int32 getAsPixels(const uint32 currentIteration = 0) const
00192 {
00193 if (currentIteration <= iteration) return computedValue;
00194 iteration = currentIteration;
00195 throw "Using auto value before computing it";
00196 }
00197
00199 virtual bool isAuto() const { return true; }
00200 };
00201
00203 struct RelativeLength : public Length
00204 {
00205
00206 public:
00208 enum RelativeUnit
00209 {
00211 em,
00213 ex,
00215 percent,
00216 };
00217
00218
00219 protected:
00221 RelativeUnit unit;
00223 const Length & to;
00224
00225
00226 public:
00228 RelativeLength(const float value, const RelativeUnit & relUnit, Length & relativeTo) : Length(value), unit(relUnit), to(relativeTo) {}
00230 RelativeLength(const RelativeLength & other) : Length(other.value), unit(other.unit), to(other.to) {}
00231
00232
00233 public:
00235 virtual int32 getAsPixels(const uint32 currentIteration = 0) const
00236 {
00237 if (currentIteration <= iteration) return computedValue;
00238 iteration = currentIteration;
00239 int32 parentPixels = to.getAsPixels(currentIteration);
00240 switch(unit)
00241 {
00242 case em:
00243 case ex:
00244 return computedValue = (int32)((float)parentPixels * value + 0.5f);
00245 case percent:
00246 return computedValue = (int32)((float)parentPixels * value * 0.01f + 0.5f);
00247 }
00248
00249 return computedValue = parentPixels;
00250 }
00251 };
00252
00254 struct AbsoluteLength : public Length
00255 {
00257 enum AbsoluteUnit
00258 {
00260 px,
00262 in,
00264 cm,
00266 mm,
00268 pt,
00270 pc,
00271 };
00272
00273
00274 protected:
00276 AbsoluteUnit unit;
00278 static float millimeterInPixels;
00279
00280
00281 public:
00283 AbsoluteLength(const float value, const AbsoluteUnit & relUnit) : Length(value), unit(relUnit) {}
00285 AbsoluteLength(const AbsoluteLength & other) : Length(other.value), unit(other.unit) {}
00286
00287
00288 public:
00290 virtual int32 getAsPixels(const uint32 currentIteration = 0) const
00291 {
00292 if (currentIteration <= iteration) return computedValue;
00293 iteration = currentIteration;
00294 switch(unit)
00295 {
00296 case in:
00297 return computedValue = (int32)(25.4f * value * millimeterInPixels + 0.5f);
00298 case cm:
00299 return computedValue = (int32)(10.0f * value * millimeterInPixels + 0.5f);
00300 case mm:
00301 return computedValue = (int32)(value * millimeterInPixels + 0.5f);
00302 case pt:
00303 return computedValue = (int32)(0.352778f * value * millimeterInPixels + 0.5f);
00304 case pc:
00305 return computedValue = (int32)(4.233333f * value * millimeterInPixels + 0.5f);
00306 case px:
00307 default:
00308 return computedValue = (int32)value;
00309 }
00310 }
00311
00313 virtual bool isAbsolute() const { return true; }
00314 };
00315
00317 class Colour
00318 {
00319 public:
00321 uint8 R, G, B, A;
00322
00323 public:
00325 Colour(const uint8 _R = 0, const uint8 _G = 0, const uint8 _B = 0, const uint8 _A = 0) : R(_R), G(_G), B(_B), A(_A) {}
00327 Colour(const char * const input, const int length) : R(0), G(0), B(0), A(0)
00328 {
00329 if (length && input[0] == '#') constructFromHex(&input[1], length - 1);
00330 else constructFromHex(input, length);
00331 }
00332
00336 inline bool fromString(const char * const input, const int length)
00337 {
00338 if (length && input[0] == '#') return constructFromHex(&input[1], length - 1);
00339 return constructFromHex(input, length);
00340 }
00341
00346 inline void toString(char * output, int & length)
00347 {
00348 if (length < 7 || !output) { length = 7; return; }
00349 length = 7;
00350 output[0] = '#';
00351 toHex(R, output[1], output[2]);
00352 toHex(G, output[3], output[4]);
00353 toHex(B, output[5], output[6]);
00354 }
00355
00357 inline const bool operator == (const Colour & colour) const { return R == colour.R && G == colour.G && B == colour.B && A == colour.A; }
00359 inline const bool operator != (const Colour & colour) const { return R != colour.R || G != colour.G || B != colour.B || A != colour.A; }
00360
00361 private:
00363 inline bool constructFromHex(const char * const input, const int length)
00364 {
00365 if (length == 6 && areHex(input, 6))
00366 {
00367 R = fromHex(input[0], input[1]);
00368 G = fromHex(input[2], input[3]);
00369 B = fromHex(input[4], input[5]);
00370 return true;
00371 } else if (length == 3 && areHex(input, 3))
00372 {
00373 R = fromHex(input[0], input[0]);
00374 G = fromHex(input[1], input[1]);
00375 B = fromHex(input[2], input[2]);
00376 return true;
00377 } else if (length > 7 && input[0] == 'r' && input[1] == 'g' && input[2] == 'b' && input[3] == '(')
00378 {
00379
00380 Colour xTmp;
00381 int pos = 4;
00382 while (input[pos] == ' ') pos++;
00383 int result = 0;
00384
00385
00386 int newPos = fromDecimal(&input[pos], length - pos, result);
00387 if (newPos == -1) return false;
00388
00389 pos += newPos;
00390 xTmp.R = clipToByte(result);
00391
00392 if (input[pos++] != ',') return false;
00393 while (input[pos] == ' ') pos++;
00394 newPos = fromDecimal(&input[pos], length - pos, result);
00395 if (newPos == -1) return false;
00396
00397 pos += newPos;
00398 xTmp.G = clipToByte(result);
00399
00400 if (input[pos++] != ',') return false;
00401 while (input[pos] == ' ') pos++;
00402 newPos = fromDecimal(&input[pos], length - pos, result);
00403 if (newPos == -1) return false;
00404
00405 pos += newPos;
00406 xTmp.B = clipToByte(result);
00407
00408 if (input[pos++] != ')') return false;
00409
00410 *this = xTmp;
00411 return true;
00412 } else
00413 {
00414 R = G = B = A = 0;
00415 return false;
00416 }
00417 }
00418
00420 inline bool areHex(const char * input, const int length) const
00421 {
00422 const char * const ptr = input + length;
00423 while (input < ptr) if (!isHex(*input)) return false; else input++;
00424 return true;
00425 }
00426
00428 inline bool isHex(const char ch) const { return (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'); }
00429
00431 inline uint8 fromHex(char high, char low) const { if (high >= 'a') high -= 32; if (low >= 'a') low -= 32; return ((high > '9' ? (high - 'A' + 10) : high - '0') << 4) | (low > '9' ? (low - 'A' + 10) : low - '0'); }
00432
00434 inline char toHex(uint8 halfVal) const { return halfVal > 9 ? ('A' + halfVal - 10) : ('0' + halfVal);}
00435
00437 inline void toHex(uint8 value, char & high, char & low) const { high = toHex(value >> 4); low = toHex(value & 0xf); }
00438
00440 inline bool isDigit(const char digit) const { return digit >= '0' && digit <= '9'; }
00441
00445 int fromDecimal(const char * const input, const int length, int & result) const
00446 {
00447 result = 0;
00448 int pos = 0;
00449 bool bNegative = (input[pos] == '-');
00450 bool bPercent = false;
00451 if (bNegative) pos++;
00452
00453 while (pos < length && (input[pos] != ',' && input[pos] != ')'))
00454 {
00455 if (input[pos] != ' ')
00456 {
00457 if (isDigit(input[pos]) && !bPercent) result = result * 10 + (input[pos] - '0');
00458 else if (input[pos] == '%') { result = (255 * result) / 100; bPercent = true; }
00459
00460 else { result = 0; return -1; }
00461 }
00462 pos++;
00463 }
00464
00465 if (bNegative) result = -result;
00466 return pos;
00467 }
00468
00470 inline uint8 clipToByte(int value) const { return (uint8)(value < 0 ? 0 : (value > 255 ? 255 : value)); }
00471 };
00472
00474 struct Colours
00475 {
00477 static Colour Black;
00478 };
00479
00480
00483 class Font
00484 {
00485 public:
00487 Length * size;
00490 uint32 UID;
00492 Colour color;
00493
00494
00495 public:
00497 Font(Length * _size, const uint32 _UID, const Colour & _color = CSS::Colours::Black) : size(_size), UID(_UID), color(_color) {}
00498 };
00499
00501 class LineHeight : public Length
00502 {
00503 private:
00505 Length * length;
00507 bool owned;
00508
00509 public:
00511 LineHeight(Length * relativeTo = 0, bool _owned = false) : length(relativeTo), Length(0), owned(_owned) {}
00513 LineHeight(const LineHeight & other) : Length(0), length(other.length), owned(other.owned) {}
00514
00515
00516 public:
00518 int32 getHeightInPixels(CSS::Font * font, const uint32 currentIteration = 0)
00519 {
00520 Length * len = length ? length : (font && font->size ? font->size : 0);
00521 int32 parentPixels = len ? len->getAsPixels(currentIteration) : (font && font->size ? font->size->getAsPixels(currentIteration) : 0);
00522
00523 setComputedValue(parentPixels, currentIteration);
00524 return parentPixels;
00525 }
00526
00528 inline Length * setNotOwnedLength(Length * const len) { Length * ret = owned ? length : 0; length = len; owned = false; return ret; }
00530 inline Length * setOwnedLength(Length * const len) { Length * ret = owned ? length : 0; length = len; owned = true; return ret; }
00532 inline bool isSet() const { return length != 0; }
00533
00534
00535 public:
00538 virtual int32 getAsPixels(const uint32 currentIteration = 0) const { return length ? length->getAsPixels(currentIteration) : 0; }
00540 virtual void setZero() { if (length) length->setZero(); }
00542 virtual bool isAuto() const { return length ? length->isAuto() : false; }
00544 virtual void setComputedValue(const int32 _value, const uint32 _iter) { if (length) length->setComputedValue(_value, _iter); }
00546 virtual const int32 getComputedValue() const { return length ? length->getComputedValue() : 0; }
00548 virtual bool isAbsolute() const { return length ? length->isAbsolute() : true; }
00549 };
00550
00551
00554 struct Unit
00555 {
00556 struct Base
00557 {
00558 };
00559
00561 struct Integer
00562 {
00563 int32 value;
00564 };
00565
00566 struct Number
00567 {
00568 float value;
00569 };
00570 };
00571
00573 struct StyleImplement
00574 {
00576 typedef CSS::Length Length;
00578 typedef CSS::Colour Colour;
00580 typedef CSS::BorderStyle::Style BorderStyle;
00582 typedef CSS::Position::Type PositionType;
00584 typedef CSS::DisplayMode::Type DisplayMode;
00586 typedef CSS::ClearAndFloat::Property ClearAndFloatType;
00588 typedef CSS::TextDecoration::Type TextDecorationType;
00589
00590
00591
00592
00594 Length * contentWidth;
00596 Length * contentHeight;
00598 Length * paddingLeft;
00600 Length * paddingTop;
00602 Length * paddingBottom;
00604 Length * paddingRight;
00606 Length * marginLeft;
00608 Length * marginTop;
00610 Length * marginBottom;
00612 Length * marginRight;
00613
00614
00616 Length * borderLeft;
00618 Colour borderLeftColor;
00620 BorderStyle borderLeftStyle;
00622 Length * borderRight;
00624 Colour borderRightColor;
00626 BorderStyle borderRightStyle;
00628 Length * borderTop;
00630 Colour borderTopColor;
00632 BorderStyle borderTopStyle;
00634 Length * borderBottom;
00636 Colour borderBottomColor;
00638 BorderStyle borderBottomStyle;
00639
00640
00642 PositionType positionType;
00644 Length * positionLeft;
00646 Length * positionTop;
00648 Length * positionBottom;
00650 Length * positionRight;
00651
00652
00654 DisplayMode displayMode;
00656 ClearAndFloatType floating;
00658 ClearAndFloatType clearing;
00660 bool leftToRight;
00661
00662
00664 CSS::LineHeight lineHeight;
00666 CSS::Font * font;
00668 CSS::TextAlign * textAlign;
00670 CSS::VerticalAlign* verticalAlign;
00672 TextDecorationType textDecoration;
00673 };
00674 }
00675
00676 #endif