1 /* 2 * Copyright 2012, 2013 Thomas Schöps 3 * Copyright 2012-2019 Kai Pastor 4 * 5 * This file is part of OpenOrienteering. 6 * 7 * OpenOrienteering is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * OpenOrienteering is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with OpenOrienteering. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 22 #ifndef OPENORIENTEERING_TEXT_SYMBOL_H 23 #define OPENORIENTEERING_TEXT_SYMBOL_H 24 25 #include "symbol.h" 26 27 #include <vector> 28 29 #include <Qt> 30 #include <QFont> 31 #include <QFontMetricsF> 32 #include <QString> 33 34 class QXmlStreamReader; 35 class QXmlStreamWriter; 36 // IWYU pragma: no_forward_declare QFontMetricsF 37 38 namespace OpenOrienteering { 39 40 class Map; 41 class MapColor; 42 class MapColorMap; 43 class Object; 44 class ObjectRenderables; 45 class SymbolPropertiesWidget; 46 class SymbolSettingDialog; 47 class TextObject; 48 class VirtualCoordVector; 49 50 51 52 /** Symbol for text, can be applied to TextObjects. 53 * 54 * NOTE: Uses a hack to disable hinting for fonts: 55 * Uses a big internal font size, internal_point_size, where hinting is 56 * neglegible and scales it down for output. 57 * TODO: A maybe better solution would be to use FreeType directly. 58 */ 59 class TextSymbol : public Symbol 60 { 61 friend class TextSymbolSettings; 62 friend class PointSymbolEditorWidget; 63 friend class OCAD8FileImport; 64 public: 65 /** Modes for text framing */ 66 enum FramingMode 67 { 68 /** Only the text itself is displayed. */ 69 NoFraming = 0, 70 71 /** 72 * The text path is drawn with a QPainter with active QPen in addition 73 * to the normal fill, resulting in a line around the letters. 74 */ 75 LineFraming = 1, 76 77 /** 78 * The text is drawn a second time with a slight offset to the main 79 * text, creating a shadow effect. 80 */ 81 ShadowFraming = 2 82 }; 83 84 /** Creates an empty text symbol. */ 85 TextSymbol(); 86 ~TextSymbol() override; 87 88 protected: 89 explicit TextSymbol(const TextSymbol& proto); 90 TextSymbol* duplicate() const override; 91 92 public: 93 void createRenderables( 94 const Object *object, 95 const VirtualCoordVector &coords, 96 ObjectRenderables &output, 97 Symbol::RenderableOptions options) const override; 98 99 using Symbol::createBaselineRenderables; 100 void createBaselineRenderables( 101 const TextObject* text_object, 102 const VirtualCoordVector &coords, 103 ObjectRenderables &output) const; 104 105 void createLineBelowRenderables(const Object* object, ObjectRenderables& output) const; 106 void colorDeletedEvent(const MapColor* color) override; 107 bool containsColor(const MapColor* color) const override; 108 const MapColor* guessDominantColor() const override; 109 void replaceColors(const MapColorMap& color_map) override; 110 void scale(double factor) override; 111 112 /** Updates the internal QFont from the font settings. */ 113 void updateQFont(); 114 115 /** Calculates the factor to convert from the real font size to the internal font size */ calculateInternalScaling()116 inline double calculateInternalScaling() const {return internal_point_size / (0.001 * font_size);} 117 118 // Getters getColor()119 inline const MapColor* getColor() const {return color;} setColor(const MapColor * color)120 inline void setColor(const MapColor* color) {this->color = color;} getFontFamily()121 inline const QString& getFontFamily() const {return font_family;} getFontSize()122 inline double getFontSize() const {return 0.001 * font_size;} isBold()123 inline bool isBold() const {return bold;} isItalic()124 inline bool isItalic() const {return italic;} isUnderlined()125 inline bool isUnderlined() const {return underline;} getLineSpacing()126 inline float getLineSpacing() const {return line_spacing;} getParagraphSpacing()127 inline double getParagraphSpacing() const {return 0.001 * paragraph_spacing;} getCharacterSpacing()128 inline double getCharacterSpacing() const {return 0.001 * character_spacing;} usesKerning()129 inline bool usesKerning() const {return kerning;} 130 QString getIconText() const; // returns a default text if no custom text is set. usesFraming()131 inline bool usesFraming() const {return framing;} getFramingColor()132 inline const MapColor* getFramingColor() const {return framing_color;} getFramingMode()133 inline int getFramingMode() const {return framing_mode;} getFramingLineHalfWidth()134 inline int getFramingLineHalfWidth() const {return framing_line_half_width;} getFramingShadowXOffset()135 inline int getFramingShadowXOffset() const {return framing_shadow_x_offset;} getFramingShadowYOffset()136 inline int getFramingShadowYOffset() const {return framing_shadow_y_offset;} hasLineBelow()137 inline bool hasLineBelow() const {return line_below;} getLineBelowColor()138 inline const MapColor* getLineBelowColor() const {return line_below_color;} getLineBelowWidth()139 inline double getLineBelowWidth() const {return 0.001 * line_below_width;} getLineBelowDistance()140 inline double getLineBelowDistance() const {return 0.001 * line_below_distance;} getNumCustomTabs()141 inline int getNumCustomTabs() const {return (int)custom_tabs.size();} getCustomTab(int index)142 inline int getCustomTab(int index) const {return custom_tabs[index];} getQFont()143 inline const QFont& getQFont() const {return qfont;} getFontMetrics()144 inline const QFontMetricsF& getFontMetrics() const { return metrics; } 145 146 double getNextTab(double pos) const; 147 148 constexpr static qreal internal_point_size = 256; 149 150 SymbolPropertiesWidget* createPropertiesWidget(SymbolSettingDialog* dialog) override; 151 152 protected: 153 void saveImpl(QXmlStreamWriter& xml, const Map& map) const override; 154 bool loadImpl(QXmlStreamReader& xml, const Map& map, SymbolDictionary& symbol_dict, int version) override; 155 bool equalsImpl(const Symbol* other, Qt::CaseSensitivity case_sensitivity) const override; 156 157 158 // Members ordered for minimizing padding 159 160 QFont qfont; 161 QFontMetricsF metrics; 162 QString font_family; 163 QString icon_text; // text to be drawn in the symbol's icon 164 165 const MapColor* color; 166 const MapColor* framing_color; 167 const MapColor* line_below_color; 168 169 std::vector<int> custom_tabs; 170 171 double tab_interval; /// default tab interval length in text coordinates 172 float line_spacing; // as factor of original line spacing 173 float character_spacing; // as a factor of the space character width 174 int font_size; // this defines the font size in 1000 mm. How big the letters really are depends on the design of the font though 175 int paragraph_spacing; // in mm 176 int framing_mode; 177 int framing_line_half_width; 178 int framing_shadow_x_offset; 179 int framing_shadow_y_offset; 180 int line_below_width; 181 int line_below_distance; 182 bool bold; 183 bool italic; 184 bool underline; 185 bool kerning; 186 bool framing; 187 bool line_below; 188 189 }; 190 191 192 } // namespace OpenOrienteering 193 194 #endif 195