1 /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */ 2 3 /* libmwaw 4 * Version: MPL 2.0 / LGPLv2+ 5 * 6 * The contents of this file are subject to the Mozilla Public License Version 7 * 2.0 (the "License"); you may not use this file except in compliance with 8 * the License or as specified alternatively below. You may obtain a copy of 9 * the License at http://www.mozilla.org/MPL/ 10 * 11 * Software distributed under the License is distributed on an "AS IS" basis, 12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 * for the specific language governing rights and limitations under the 14 * License. 15 * 16 * Major Contributor(s): 17 * Copyright (C) 2002 William Lachance (wrlach@gmail.com) 18 * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net) 19 * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) 20 * Copyright (C) 2006, 2007 Andrew Ziem 21 * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr) 22 * 23 * 24 * All Rights Reserved. 25 * 26 * For minor contributions see the git repository. 27 * 28 * Alternatively, the contents of this file may be used under the terms of 29 * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), 30 * in which case the provisions of the LGPLv2+ are applicable 31 * instead of those above. 32 */ 33 34 #ifndef MWAW_FONT 35 # define MWAW_FONT 36 37 #include <string> 38 #include <vector> 39 40 #include "libmwaw_internal.hxx" 41 42 //! Class to store font 43 class MWAWFont 44 { 45 public: 46 /** a small struct to define a line in MWAWFont */ 47 struct Line { 48 /** the line style */ 49 enum Style { None, Simple, Dot, LargeDot, Dash, Wave }; 50 /** the line style */ 51 enum Type { Single, Double, Triple }; 52 //! constructor LineMWAWFont::Line53 explicit Line(Style style=None, Type type=Single, bool wordFlag=false, float w=1.0) 54 : m_style(style) 55 , m_type(type) 56 , m_width(w) 57 , m_color(MWAWColor::black()) 58 , m_word(wordFlag) 59 { 60 } 61 //! return true if the line is not empty isSetMWAWFont::Line62 bool isSet() const 63 { 64 return m_style != None && m_width>0; 65 } 66 //! add a line to the propList knowing the type (line-through, underline, overline ) 67 void addTo(librevenge::RVNGPropertyList &propList, std::string const &type) const; 68 //! operator<< 69 friend std::ostream &operator<<(std::ostream &o, Line const &line); 70 //! operator== operator ==MWAWFont::Line71 bool operator==(Line const &oth) const 72 { 73 return cmp(oth)==0; 74 } 75 //! operator!= operator !=MWAWFont::Line76 bool operator!=(Line const &oth) const 77 { 78 return cmp(oth)!=0; 79 } 80 //! small comparison function cmpMWAWFont::Line81 int cmp(Line const &oth) const 82 { 83 if (m_style != oth.m_style) return int(m_style)-int(oth.m_style); 84 if (m_type != oth.m_type) return int(m_type)-int(oth.m_type); 85 if (m_word != oth.m_word) return m_word ? -1 : 1; 86 if (m_width < oth.m_width) return -1; 87 if (m_width > oth.m_width) return 1; 88 if (m_color.isSet() != oth.m_color.isSet()) 89 return m_color.isSet(); 90 if (m_color.get() < oth.m_color.get()) return -1; 91 if (m_color.get() > oth.m_color.get()) return 1; 92 return 0; 93 } 94 /** the style */ 95 Style m_style; 96 /** the type */ 97 Type m_type; 98 /** the width in point */ 99 float m_width; 100 /** the color ( if not set, we use the font color )*/ 101 MWAWVariable<MWAWColor> m_color; 102 /** word or not word line */ 103 bool m_word; 104 }; 105 /** a small struct to define the script position in MWAWFont */ 106 struct Script { 107 //! constructor ScriptMWAWFont::Script108 explicit Script(float delta=0, librevenge::RVNGUnit deltaUnit=librevenge::RVNG_PERCENT, int scale=100) 109 : m_delta(delta) 110 , m_deltaUnit(deltaUnit) 111 , m_scale(scale) 112 { 113 } 114 //! return true if the position is not default isSetMWAWFont::Script115 bool isSet() const 116 { 117 return *this != Script(); 118 } 119 //! return a yposition which correspond to a basic subscript subMWAWFont::Script120 static Script sub() 121 { 122 return Script(-33,librevenge::RVNG_PERCENT,58); 123 } 124 //! return a yposition which correspond to a basic subscript100 sub100MWAWFont::Script125 static Script sub100() 126 { 127 return Script(-20); 128 } 129 //! return a yposition which correspond to a basic superscript superMWAWFont::Script130 static Script super() 131 { 132 return Script(33,librevenge::RVNG_PERCENT,58); 133 } 134 //! return a yposition which correspond to a basic superscript100 super100MWAWFont::Script135 static Script super100() 136 { 137 return Script(20); 138 } 139 //! return a string which correspond to style:text-position 140 std::string str(float fSize) const; 141 142 //! operator== operator ==MWAWFont::Script143 bool operator==(Script const &oth) const 144 { 145 return cmp(oth)==0; 146 } 147 //! operator!= operator !=MWAWFont::Script148 bool operator!=(Script const &oth) const 149 { 150 return cmp(oth)!=0; 151 } 152 //! operator< operator <MWAWFont::Script153 bool operator<(Script const &oth) const 154 { 155 return cmp(oth)<0; 156 } 157 //! operator<= operator <=MWAWFont::Script158 bool operator<=(Script const &oth) const 159 { 160 return cmp(oth)<=0; 161 } 162 //! operator> operator >MWAWFont::Script163 bool operator>(Script const &oth) const 164 { 165 return cmp(oth)>0; 166 } 167 //! operator>= operator >=MWAWFont::Script168 bool operator>=(Script const &oth) const 169 { 170 return cmp(oth)>=0; 171 } 172 //! small comparison function cmpMWAWFont::Script173 int cmp(Script const &oth) const 174 { 175 if (m_delta > oth.m_delta) return -1; 176 if (m_delta < oth.m_delta) return 1; 177 if (m_deltaUnit != oth.m_deltaUnit) return int(m_deltaUnit)-int(oth.m_deltaUnit); 178 if (m_scale != oth.m_scale) return m_scale-oth.m_scale; 179 return 0; 180 } 181 //! the ydelta 182 float m_delta; 183 //! the ydelta unit ( point or percent ) 184 librevenge::RVNGUnit m_deltaUnit; 185 //! the font scaling ( in percent ) 186 int m_scale; 187 }; 188 189 //! the different font bit 190 enum FontBits { boldBit=1, italicBit=2, blinkBit=4, embossBit=8, engraveBit=0x10, 191 hiddenBit=0x20, outlineBit=0x40, shadowBit=0x80, 192 reverseVideoBit=0x100, smallCapsBit=0x200, uppercaseBit=0x400, 193 lowercaseBit=0x800, 194 initialcaseBit=2*lowercaseBit, 195 boxedBit=2*initialcaseBit, 196 boxedRoundedBit=2*boxedBit, 197 reverseWritingBit=2*boxedRoundedBit 198 }; 199 /** constructor 200 * 201 * \param newId system id font 202 * \param sz the font size 203 * \param f the font attributes bold, ... */ MWAWFont(int newId=-1,float sz=12,uint32_t f=0)204 explicit MWAWFont(int newId=-1, float sz=12, uint32_t f = 0) 205 : m_id(newId) 206 , m_size(sz) 207 , m_sizeIsRelative(false) 208 , m_deltaSpacing(0) 209 , m_deltaSpacingUnit(librevenge::RVNG_POINT) 210 , m_widthStreching(1) 211 , m_scriptPosition() 212 , m_flags(f) 213 , m_overline(Line(Line::None)) 214 , m_strikeoutline(Line(Line::None)) 215 , m_underline(Line(Line::None)) 216 , m_color(MWAWColor::black()) 217 , m_backgroundColor(MWAWColor::white()) 218 , m_language("") 219 , m_extra("") 220 { 221 resetColor(); 222 } 223 //! returns true if the font id is initialized isSet() const224 bool isSet() const 225 { 226 return m_id.isSet(); 227 } 228 //! inserts the set value in the current font insert(MWAWFont const & ft)229 void insert(MWAWFont const &ft) 230 { 231 m_id.insert(ft.m_id); 232 m_size.insert(ft.m_size); 233 m_sizeIsRelative.insert(ft.m_sizeIsRelative); 234 m_deltaSpacing.insert(ft.m_deltaSpacing); 235 m_deltaSpacingUnit.insert(ft.m_deltaSpacingUnit); 236 m_widthStreching.insert(ft.m_widthStreching); 237 m_scriptPosition.insert(ft.m_scriptPosition); 238 if (ft.m_flags.isSet()) { 239 if (m_flags.isSet()) 240 setFlags(flags()| ft.flags()); 241 else 242 m_flags = ft.m_flags; 243 } 244 m_overline.insert(ft.m_overline); 245 m_strikeoutline.insert(ft.m_strikeoutline); 246 m_underline.insert(ft.m_underline); 247 m_color.insert(ft.m_color); 248 m_backgroundColor.insert(ft.m_backgroundColor); 249 m_extra += ft.m_extra; 250 } 251 //! sets the font id and resets size to the previous size for this font setFont(int newId)252 void setFont(int newId) 253 { 254 resetColor(); 255 m_id=newId; 256 } 257 258 //! returns the font id id() const259 int id() const 260 { 261 return m_id.get(); 262 } 263 //! sets the font id setId(int newId)264 void setId(int newId) 265 { 266 m_id = newId; 267 } 268 269 //! returns the font size size() const270 float size() const 271 { 272 return m_size.get(); 273 } 274 //! sets the font size setSize(float sz,bool isRelative=false)275 void setSize(float sz, bool isRelative=false) 276 { 277 m_size = sz; 278 m_sizeIsRelative = isRelative; 279 } 280 281 //! returns the condensed(negative)/extended(positive) width deltaLetterSpacing() const282 float deltaLetterSpacing() const 283 { 284 return m_deltaSpacing.get(); 285 } 286 //! returns the condensed(negative)/extended(positive) unit deltaLetterSpacingUnit() const287 librevenge::RVNGUnit deltaLetterSpacingUnit() const 288 { 289 return m_deltaSpacingUnit.get(); 290 } 291 //! sets the letter spacing ( delta value in point ) setDeltaLetterSpacing(float d,librevenge::RVNGUnit unit=librevenge::RVNG_POINT)292 void setDeltaLetterSpacing(float d, librevenge::RVNGUnit unit=librevenge::RVNG_POINT) 293 { 294 m_deltaSpacing=d; 295 m_deltaSpacingUnit=unit; 296 } 297 //! returns the text width streching widthStreching() const298 float widthStreching() const 299 { 300 return m_widthStreching.get(); 301 } 302 //! sets the text width streching setWidthStreching(float scale=1.0)303 void setWidthStreching(float scale=1.0) 304 { 305 m_widthStreching = scale; 306 } 307 //! returns the script position script() const308 Script const &script() const 309 { 310 return m_scriptPosition.get(); 311 } 312 313 //! sets the script position set(Script const & newscript)314 void set(Script const &newscript) 315 { 316 m_scriptPosition = newscript; 317 } 318 319 //! returns the font flags flags() const320 uint32_t flags() const 321 { 322 return m_flags.get(); 323 } 324 //! sets the font attributes bold, ... setFlags(uint32_t fl)325 void setFlags(uint32_t fl) 326 { 327 m_flags = fl; 328 } 329 330 //! returns true if the font color is not black hasColor() const331 bool hasColor() const 332 { 333 return m_color.isSet() && !m_color.get().isBlack(); 334 } 335 //! returns the font color getColor(MWAWColor & c) const336 void getColor(MWAWColor &c) const 337 { 338 c = m_color.get(); 339 } 340 //! sets the font color setColor(MWAWColor color)341 void setColor(MWAWColor color) 342 { 343 m_color = color; 344 } 345 346 //! returns the font background color getBackgroundColor(MWAWColor & c) const347 void getBackgroundColor(MWAWColor &c) const 348 { 349 c = m_backgroundColor.get(); 350 } 351 //! sets the font background color setBackgroundColor(MWAWColor color)352 void setBackgroundColor(MWAWColor color) 353 { 354 m_backgroundColor = color; 355 } 356 //! resets the font color to black and the background color to white resetColor()357 void resetColor() 358 { 359 m_color = MWAWColor::black(); 360 m_backgroundColor = MWAWColor::white(); 361 } 362 363 //! return true if the font has decorations line (overline, strikeout, underline) hasDecorationLines() const364 bool hasDecorationLines() const 365 { 366 return (m_overline.isSet() && m_overline->isSet()) || 367 (m_strikeoutline.isSet() && m_strikeoutline->isSet()) || 368 (m_underline.isSet() && m_underline->isSet()); 369 } 370 //! reset the decoration resetDecorationLines()371 void resetDecorationLines() 372 { 373 if (m_overline.isSet()) m_overline=Line(Line::None); 374 if (m_strikeoutline.isSet()) m_strikeoutline=Line(Line::None); 375 if (m_underline.isSet()) m_underline=Line(Line::None); 376 } 377 //! returns the overline getOverline() const378 Line const &getOverline() const 379 { 380 return m_overline.get(); 381 } 382 //! sets the overline setOverline(Line const & line)383 void setOverline(Line const &line) 384 { 385 m_overline = line; 386 } 387 //! sets the overline style ( by default, we also reset the style) setOverlineStyle(Line::Style style=Line::None,bool doReset=true)388 void setOverlineStyle(Line::Style style=Line::None, bool doReset=true) 389 { 390 if (doReset) 391 m_overline = Line(style); 392 else 393 m_overline->m_style = style; 394 } 395 //! sets the overline type setOverlineType(Line::Type type=Line::Single)396 void setOverlineType(Line::Type type=Line::Single) 397 { 398 m_overline->m_type = type; 399 } 400 //! sets the overline word flag setOverlineWordFlag(bool wordFlag=false)401 void setOverlineWordFlag(bool wordFlag=false) 402 { 403 m_overline->m_word = wordFlag; 404 } 405 //! sets the overline width setOverlineWidth(float w)406 void setOverlineWidth(float w) 407 { 408 m_overline->m_width = w; 409 } 410 //! sets the overline color setOverlineColor(MWAWColor const & color)411 void setOverlineColor(MWAWColor const &color) 412 { 413 m_overline->m_color = color; 414 } 415 416 //! returns the strikeoutline getStrikeOut() const417 Line const &getStrikeOut() const 418 { 419 return m_strikeoutline.get(); 420 } 421 //! sets the strikeoutline setStrikeOut(Line const & line)422 void setStrikeOut(Line const &line) 423 { 424 m_strikeoutline = line; 425 } 426 //! sets the strikeoutline style ( by default, we also reset the style) setStrikeOutStyle(Line::Style style=Line::None,bool doReset=true)427 void setStrikeOutStyle(Line::Style style=Line::None, bool doReset=true) 428 { 429 if (doReset) 430 m_strikeoutline = Line(style); 431 else 432 m_strikeoutline->m_style = style; 433 } 434 //! sets the strikeoutline type setStrikeOutType(Line::Type type=Line::Single)435 void setStrikeOutType(Line::Type type=Line::Single) 436 { 437 m_strikeoutline->m_type = type; 438 } 439 //! sets the strikeoutline word flag setStrikeOutWordFlag(bool wordFlag=false)440 void setStrikeOutWordFlag(bool wordFlag=false) 441 { 442 m_strikeoutline->m_word = wordFlag; 443 } 444 //! sets the strikeoutline width setStrikeOutWidth(float w)445 void setStrikeOutWidth(float w) 446 { 447 m_strikeoutline->m_width = w; 448 } 449 //! sets the strikeoutline color setStrikeOutColor(MWAWColor const & color)450 void setStrikeOutColor(MWAWColor const &color) 451 { 452 m_strikeoutline->m_color = color; 453 } 454 455 //! returns the underline getUnderline() const456 Line const &getUnderline() const 457 { 458 return m_underline.get(); 459 } 460 //! sets the underline setUnderline(Line const & line)461 void setUnderline(Line const &line) 462 { 463 m_underline = line; 464 } 465 //! sets the underline style ( by default, we also reset the style) setUnderlineStyle(Line::Style style=Line::None,bool doReset=true)466 void setUnderlineStyle(Line::Style style=Line::None, bool doReset=true) 467 { 468 if (doReset) 469 m_underline = Line(style); 470 else 471 m_underline->m_style = style; 472 } 473 //! sets the underline type setUnderlineType(Line::Type type=Line::Single)474 void setUnderlineType(Line::Type type=Line::Single) 475 { 476 m_underline->m_type = type; 477 } 478 //! sets the underline word flag setUnderlineWordFlag(bool wordFlag=false)479 void setUnderlineWordFlag(bool wordFlag=false) 480 { 481 m_underline->m_word = wordFlag; 482 } 483 //! sets the underline width setUnderlineWidth(float w)484 void setUnderlineWidth(float w) 485 { 486 m_underline->m_width = w; 487 } 488 //! sets the underline color setUnderlineColor(MWAWColor const & color)489 void setUnderlineColor(MWAWColor const &color) 490 { 491 m_underline->m_color = color; 492 } 493 494 //! returns the language language() const495 std::string const &language() const 496 { 497 return m_language.get(); 498 } 499 //! set the language ( in the for en_US, en_GB, en, ...) setLanguage(std::string const & lang)500 void setLanguage(std::string const &lang) 501 { 502 m_language=lang; 503 } 504 //! add to the propList 505 void addTo(librevenge::RVNGPropertyList &propList, std::shared_ptr<MWAWFontConverter> fontConverter) const; 506 //! add to the propList to a list level 507 void addToListLevel(librevenge::RVNGPropertyList &propList, std::shared_ptr<MWAWFontConverter> fontConverter) const; 508 509 //! returns a string which can be used for debugging 510 std::string getDebugString(std::shared_ptr<MWAWFontConverter> &converter) const; 511 512 //! operator== operator ==(MWAWFont const & f) const513 bool operator==(MWAWFont const &f) const 514 { 515 return cmp(f) == 0; 516 } 517 //! operator!= operator !=(MWAWFont const & f) const518 bool operator!=(MWAWFont const &f) const 519 { 520 return cmp(f) != 0; 521 } 522 523 //! a comparison function cmp(MWAWFont const & oth) const524 int cmp(MWAWFont const &oth) const 525 { 526 int diff = id() - oth.id(); 527 if (diff != 0) return diff; 528 if (size() < oth.size()) return -1; 529 if (size() > oth.size()) return 1; 530 if (m_sizeIsRelative.get() != oth.m_sizeIsRelative.get()) return m_sizeIsRelative.get() ? 1 : -1; 531 if (flags() < oth.flags()) return -1; 532 if (flags() > oth.flags()) return 1; 533 if (m_deltaSpacing.get() < oth.m_deltaSpacing.get()) return -1; 534 if (m_deltaSpacing.get() > oth.m_deltaSpacing.get()) return 1; 535 if (m_deltaSpacingUnit.get() < oth.m_deltaSpacingUnit.get()) return -1; 536 if (m_deltaSpacingUnit.get() > oth.m_deltaSpacingUnit.get()) return 1; 537 if (m_widthStreching.get() < oth.m_widthStreching.get()) return -1; 538 if (m_widthStreching.get() > oth.m_widthStreching.get()) return 1; 539 diff = script().cmp(oth.script()); 540 if (diff != 0) return diff; 541 diff = m_overline.get().cmp(oth.m_overline.get()); 542 if (diff != 0) return diff; 543 diff = m_strikeoutline.get().cmp(oth.m_strikeoutline.get()); 544 if (diff != 0) return diff; 545 diff = m_underline.get().cmp(oth.m_underline.get()); 546 if (diff != 0) return diff; 547 if (m_color.get() < oth.m_color.get()) return -1; 548 if (m_color.get() > oth.m_color.get()) return 1; 549 if (m_backgroundColor.get() < oth.m_backgroundColor.get()) return -1; 550 if (m_backgroundColor.get() > oth.m_backgroundColor.get()) return 1; 551 if (m_language.get() < oth.m_language.get()) return -1; 552 if (m_language.get() > oth.m_language.get()) return 1; 553 return diff; 554 } 555 556 protected: 557 MWAWVariable<int> m_id /** font identificator*/; 558 MWAWVariable<float> m_size /** font size */; 559 MWAWVariable<bool> m_sizeIsRelative /** true if the size is percent */; 560 MWAWVariable<float> m_deltaSpacing /** expand(> 0), condensed(< 0) depl*/; 561 MWAWVariable<librevenge::RVNGUnit> m_deltaSpacingUnit /** the delta spacing unit */; 562 MWAWVariable<float> m_widthStreching /** the width streching in percent */; 563 MWAWVariable<Script> m_scriptPosition /** the sub/super script definition */; 564 MWAWVariable<uint32_t> m_flags /** font attributes */; 565 MWAWVariable<Line> m_overline /** overline attributes */; 566 MWAWVariable<Line> m_strikeoutline /** overline attributes */; 567 MWAWVariable<Line> m_underline /** underline attributes */; 568 MWAWVariable<MWAWColor> m_color /** font color */; 569 MWAWVariable<MWAWColor> m_backgroundColor /** font background color */; 570 MWAWVariable<std::string> m_language /** the language if set */; 571 public: 572 //! extra data 573 std::string m_extra; 574 }; 575 576 namespace MWAWFontManagerInternal 577 { 578 struct State; 579 } 580 581 //! a font manager which can be used to store fonts, ... 582 class MWAWFontManager 583 { 584 public: 585 //! constructor 586 explicit MWAWFontManager(std::shared_ptr<MWAWFontConverter> const &fontConverter); 587 //! destructor 588 ~MWAWFontManager(); 589 //! returns a span id which can be used to call the list 590 int getId(MWAWFont const &font); 591 //! returns the font corresponding to an id 592 bool getFont(int id, MWAWFont &font) const; 593 //! returns the font converter 594 std::shared_ptr<MWAWFontConverter> getFontConverter(); 595 protected: 596 //! the state 597 std::shared_ptr<MWAWFontManagerInternal::State> m_state; 598 private: 599 MWAWFontManager(MWAWFontManager const &) = delete; 600 MWAWFontManager &operator=(MWAWFontManager const &) = delete; 601 }; 602 #endif 603 // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: 604