LibreOffice Module xmerge (master) 1
TextStyle.java
Go to the documentation of this file.
1/*
2 * This file is part of the LibreOffice project.
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 *
8 * This file incorporates work covered by the following license notice:
9 *
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
17 */
18
19// DJP ToDo: need way of specifying fg/bg colors on ws->DOM
20
21package org.openoffice.xmerge.converter.xml;
22
23import java.awt.Color;
24
25import org.w3c.dom.NodeList;
26import org.w3c.dom.Node;
27import org.w3c.dom.NamedNodeMap;
28import org.w3c.dom.Element;
29
31
35public class TextStyle extends Style implements Cloneable {
36
38 final private static int BOLD = 0x01;
40 final private static int ITALIC = 0x02;
42 final private static int UNDERLINE = 0x04;
44 final private static int STRIKETHRU = 0x08;
46 final private static int SUPERSCRIPT = 0x10;
48 final private static int SUBSCRIPT = 0x20;
49
51 private int values = 0;
53 private int mask = 0;
54
56 private int sizeInPoints = 0;
58 private String fontName = null;
60 private Color fontColor = null;
62 private Color bgColor = null;
63
73 public TextStyle(Node node, StyleCatalog sc) {
74 super(node, sc);
75
76 // Run through the attributes of this node, saving
77 // the ones we're interested in.
78 NamedNodeMap attrNodes = node.getAttributes();
79 if (attrNodes != null) {
80 int len = attrNodes.getLength();
81 for (int i = 0; i < len; i++) {
82 Node attr = attrNodes.item(i);
83 handleAttribute(attr.getNodeName(), attr.getNodeValue());
84 }
85 }
86
87 // Look for children. Only ones we care about are "style:properties"
88 // nodes. If any are found, recursively traverse them, passing
89 // along the style element to add properties to.
90 if (!node.hasChildNodes()) {
91 return;
92 }
93 NodeList children = node.getChildNodes();
94 int len = children.getLength();
95 for (int i = 0; i < len; i++) {
96 Node child = children.item(i);
97 String nodeName = child.getNodeName();
98 if (nodeName.equals("style:properties")) {
99 NamedNodeMap childAttrNodes = child.getAttributes();
100 if (childAttrNodes != null) {
101 int nChildAttrNodes = childAttrNodes.getLength();
102 for (int j = 0; j < nChildAttrNodes; j++) {
103 Node attr = childAttrNodes.item(j);
104 handleAttribute(attr.getNodeName(),
105 attr.getNodeValue());
106 }
107 }
108 }
109 }
110 }
111
138 public TextStyle(String name, String family, String parent,
139 int mask, int values, int fontSize, String fontName, StyleCatalog sc) {
140 super(name, family, parent, sc);
141 this.mask = mask;
142 this.values = values;
143 this.sizeInPoints = fontSize;
144 this.fontName = fontName;
145 }
146
154 private Color parseColorString(String value) {
155 int red = 0;
156 int green = 0;
157 int blue = 0;
158 try {
159 // Assume color value is of form #rrggbb
160 red = Integer.parseInt(value.substring(1, 3), 16);
161 green = Integer.parseInt(value.substring(3, 5), 16);
162 blue = Integer.parseInt(value.substring(5, 7), 16);
163 } catch (NumberFormatException e) {
164 Debug.log(Debug.ERROR, "Problem parsing a color string", e);
165 } catch (IndexOutOfBoundsException e) {
166 Debug.log(Debug.ERROR, "Problem parsing a color string", e);
167 }
168 return new Color(red, green, blue);
169 }
170
177 private void handleAttribute(String attr, String value) {
178
179 if (attr.equals("fo:font-weight")) {
180 if (value.equals("bold")) turnAttributesOn(BOLD);
181 else if (value.equals("normal")) turnAttributesOff(BOLD);
182 }
183
184 else if (attr.equals("fo:font-style")) {
185 if (value.equals("italic")) turnAttributesOn(ITALIC);
186 else if (value.equals("oblique")) turnAttributesOn(ITALIC);
187 else if (value.equals("normal")) turnAttributesOff(ITALIC);
188 }
189
190 else if (attr.equals("style:text-underline")) {
191 if (value.equals("none"))
193 else
195 }
196
197 else if (attr.equals("style:text-crossing-out")) {
198 if (value.equals("none"))
200 else
202 }
203
204 else if (attr.equals("style:text-position")) {
205 if (value.startsWith("super "))
207 else if (value.startsWith("sub "))
209 else if (value.startsWith("0% "))
211 else {
212 String firstPart = value.substring(0, value.indexOf(' '));
213 if (firstPart.endsWith("%")) {
214 firstPart = firstPart.substring(0, value.indexOf('%'));
215 int amount;
216 try {
217 amount = Integer.parseInt(firstPart);
218 } catch (NumberFormatException e) {
219 amount = 0;
220 Debug.log(Debug.ERROR, "Problem with style:text-position tag", e);
221 }
222 if (amount < 0) turnAttributesOn(SUBSCRIPT);
223 else if (amount > 0) turnAttributesOn(SUPERSCRIPT);
224 }
225 }
226 }
227
228 else if (attr.equals("fo:font-size")) {
229 if (value.endsWith("pt")) {
230 String num = value.substring(0, value.length() - 2);
231 sizeInPoints = Integer.parseInt(num);
232 }
233 }
234
235 else if (attr.equals("style:font-name"))
236 fontName = value;
237
238 else if (attr.equals("fo:color"))
240
241 else if (attr.equals("style:text-background-color"))
243
244 else if (isIgnored(attr)) {}
245
246 else {
247 Debug.log(Debug.INFO, "TextStyle Unhandled: " + attr + "=" + value);
248 }
249 }
250
256 public int getFontSize() {
257 return sizeInPoints;
258 }
259
267 return fontName;
268 }
269
278 return fontColor;
279 }
280
290 return bgColor;
291 }
292
302 @Override
304 // Create a new object to return, which is a clone of this one.
305 TextStyle resolved = null;
306 try {
307 resolved = (TextStyle)this.clone();
308 } catch (Exception e) {
309 Debug.log(Debug.ERROR, "Can't clone", e);
310 }
311
312 // Look up the parentStyle. (If there is no style catalog
313 // specified, we can't do any lookups.)
314 TextStyle parentStyle = null;
315 if (sc != null) {
316 if (parent != null) {
317 parentStyle = (TextStyle)sc.lookup(parent, family, null,
318 this.getClass());
319 if (parentStyle == null)
320 Debug.log(Debug.ERROR, "parent style lookup of "
321 + parent + " failed!");
322 else
323 parentStyle = (TextStyle)parentStyle.getResolved();
324
325 } else if (!name.equals("DEFAULT_STYLE")) {
326 parentStyle = (TextStyle)sc.lookup("DEFAULT_STYLE", null,
327 null, this.getClass());
328 }
329 }
330
331 // If we found a parent, for any attributes which we don't have
332 // set, try to get the values from the parent.
333 if (parentStyle != null) {
334 parentStyle = (TextStyle)parentStyle.getResolved();
335
336 if ((sizeInPoints == 0) && (parentStyle.sizeInPoints != 0))
337 resolved.sizeInPoints = parentStyle.sizeInPoints;
338 if ((fontName == null) && (parentStyle.fontName != null))
339 resolved.fontName = parentStyle.fontName;
340 if ((fontColor == null) && (parentStyle.fontColor != null))
341 resolved.fontColor = parentStyle.fontColor;
342 if ((bgColor == null) && (parentStyle.bgColor != null))
343 resolved.bgColor = parentStyle.bgColor;
344 for (int m = BOLD; m <= SUBSCRIPT; m = m << 1) {
345 if (((mask & m) == 0) && ((parentStyle.mask & m) != 0)) {
346 resolved.mask |= m;
347 resolved.values |= (parentStyle.mask & m);
348 }
349 }
350
351 }
352 return resolved;
353 }
354
360 private void turnAttributesOn(int flags) {
361 mask |= flags;
362 values |= flags;
363 }
364
370 private void turnAttributesOff(int flags) {
371 mask |= flags;
372 values &= ~flags;
373 }
374
383 private static String toCSV(String value) {
384 if (value != null)
385 return "\"" + value + "\",";
386 else
387 return "\"\",";
388 }
389
398 private static String toLastCSV(String value) {
399 if (value != null)
400 return "\"" + value + "\"";
401 else
402 return "\"\"";
403 }
404
408 public static void dumpHdr() {
409 System.out.println(toCSV("Name") + toCSV("Family") + toCSV("parent")
410 + toCSV("Font") + toCSV("Size")
411 + toCSV("Bold") + toCSV("Italic") + toCSV("Underline")
412 + toCSV("Strikethru") + toCSV("Superscript") + toLastCSV("Subscript"));
413 }
414
418 public void dumpCSV() {
419 StringBuilder attributes = new StringBuilder();
420 for (int bitVal = 0x01; bitVal <= 0x20; bitVal = bitVal << 1) {
421 if ((bitVal & mask) != 0) {
422 attributes.append(toCSV(((bitVal & values) != 0) ? "yes" : "no"));
423 }
424 else {
425 attributes.append(toCSV(null)); // unspecified
426 }
427 }
428 System.out.println(toCSV(name) + toCSV(family) + toCSV(parent)
429 + toCSV(fontName) + toCSV("" + sizeInPoints) + attributes.toString() + toLastCSV(null));
430 }
431
442 @Override
443 public Node createNode(org.w3c.dom.Document parentDoc, String name) {
444 Element node = parentDoc.createElement(name);
445 writeAttributes(node);
446 return node;
447 }
448
458 @Override
459 public boolean isSubset(Style style) {
460 if (style.getClass() != this.getClass())
461 return false;
462 TextStyle tStyle = (TextStyle)style;
463
464 if (tStyle.values != values)
465 return false;
466
467 if (tStyle.sizeInPoints != 0 && sizeInPoints != tStyle.sizeInPoints)
468 return false;
469
470 if (tStyle.fontName != null) {
471 if (fontName == null)
472 return false;
473 if (!fontName.equals(tStyle.fontName))
474 return false;
475 }
476
477 if (tStyle.fontColor != null) {
478 if (fontColor == null)
479 return false;
480 if (!fontColor.equals(tStyle.fontColor))
481 return false;
482 }
483
484 if (tStyle.bgColor != null) {
485 if (bgColor == null)
486 return false;
487 if (!bgColor.equals(tStyle.bgColor))
488 return false;
489 }
490
491 return true;
492 }
493
500 private void writeAttributes(Element node) {
501
502 if ((mask & BOLD) != 0 && (values & BOLD) != 0)
503 node.setAttribute("fo:font-weight", "bold");
504
505 if ((mask & ITALIC) != 0 && (values & ITALIC) != 0)
506 node.setAttribute("fo:font-style", "italic");
507
508 if ((mask & UNDERLINE) != 0 && (values & UNDERLINE) != 0)
509 node.setAttribute("style:text-underline", "single");
510
511 if ((mask & STRIKETHRU) != 0 && (values & STRIKETHRU) != 0)
512 node.setAttribute("style:text-crossing-out", "single-line");
513
514 if ((mask & SUPERSCRIPT) != 0 && (values & SUPERSCRIPT) != 0)
515 node.setAttribute("style:text-position", "super 58%");
516
517 if ((mask & SUBSCRIPT) != 0 && (values & SUBSCRIPT) != 0)
518 node.setAttribute("style:text-position", "sub 58%");
519
520 if (sizeInPoints != 0) {
521 node.setAttribute("fo:font-size", Integer.toString(sizeInPoints) + "pt");
522 }
523
524 if (fontName != null)
525 node.setAttribute("style:font-name", fontName);
526
527 if (fontColor != null)
528 node.setAttribute("fo:color", buildColorString(fontColor));
529
530 if (bgColor != null)
531 node.setAttribute("style:text-background-color",
533 }
534
542 private String buildColorString(Color c) {
543 return String.format("#%06X", c.getRGB() & 0x00FFFFFF);
544 }
545
546 private static String[] ignored = {
547 "style:text-autospace", "style:text-underline-color",
548 "fo:margin-left", "fo:margin-right", "fo:text-indent",
549 "fo:margin-top", "fo:margin-bottom", "text:line-number",
550 "text:number-lines", "style:country-asian",
551 "style:font-size-asian", "style:font-name-complex",
552 "style:language-complex", "style:country-complex",
553 "style:font-size-complex", "style:punctuation-wrap",
554 "fo:language", "fo:country",
555 "style:font-name-asian", "style:language-asian",
556 "style:line-break", "fo:keep-with-next"
557 };
558
567 private boolean isIgnored(String attribute) {
568 for (String ignored1 : ignored) {
569 if (ignored1.equals(attribute)) {
570 return true;
571 }
572 }
573 return false;
574 }
575}
A StyleCatalog holds a collection of Style objects.
An object of class Style represents a style in an OpenOffice document.
Definition: Style.java:34
String parent
Parent of the Style.
Definition: Style.java:41
String family
Family of the Style.
Definition: Style.java:39
String name
Name of the Style.
Definition: Style.java:37
Represents a text Style in an OpenOffice document.
Definition: TextStyle.java:35
boolean isSubset(Style style)
Return true if style specifies as much or less than this Style, and nothing it specifies contradicts ...
Definition: TextStyle.java:459
final static int ITALIC
Indicates italic text.
Definition: TextStyle.java:40
String getFontName()
Return the name of the font for this Style.
Definition: TextStyle.java:266
Color getBackgroundColor()
Return the background Color for this Style.
Definition: TextStyle.java:289
void handleAttribute(String attr, String value)
Set an attribute.
Definition: TextStyle.java:177
boolean isIgnored(String attribute)
This code checks whether an attribute is one that we intentionally ignore.
Definition: TextStyle.java:567
int values
Values of text attributes.
Definition: TextStyle.java:51
static String toCSV(String value)
Private function to return the value as an element in a Comma Separated Value (CSV) format.
Definition: TextStyle.java:383
Style getResolved()
Return a Style object corresponding to this one, but with all of the inherited information from paren...
Definition: TextStyle.java:303
Color parseColorString(String value)
Parse a color specification of the form #rrggbb
Definition: TextStyle.java:154
TextStyle(Node node, StyleCatalog sc)
Constructor for use when going from DOM to client device format.
Definition: TextStyle.java:73
void writeAttributes(Element node)
Write this Style object's attributes to a Node in the Document.
Definition: TextStyle.java:500
int mask
Bitwise mask of text attributes.
Definition: TextStyle.java:53
void dumpCSV()
Dump this Style as a Comma Separated Value (CSV) line.
Definition: TextStyle.java:418
void turnAttributesOff(int flags)
Set one or more text attributes to off.
Definition: TextStyle.java:370
void turnAttributesOn(int flags)
Set one or more text attributes to on.
Definition: TextStyle.java:360
final static int STRIKETHRU
Indicates strike-through in the text.
Definition: TextStyle.java:44
TextStyle(String name, String family, String parent, int mask, int values, int fontSize, String fontName, StyleCatalog sc)
Constructor for use when going from client device format to DOM.
Definition: TextStyle.java:138
final static int SUBSCRIPT
Indicates subscripted text.
Definition: TextStyle.java:48
final static int BOLD
Indicates bold text.
Definition: TextStyle.java:38
Node createNode(org.w3c.dom.Document parentDoc, String name)
Create a new Node in the Document, and write this Style to it.
Definition: TextStyle.java:443
int getFontSize()
Return the font size for this Style.
Definition: TextStyle.java:256
final static int UNDERLINE
Indicates underlined text.
Definition: TextStyle.java:42
static void dumpHdr()
Print a Comma Separated Value (CSV) header line for the spreadsheet dump.
Definition: TextStyle.java:408
String buildColorString(Color c)
Given a Color, return a string of the form #rrggbb.
Definition: TextStyle.java:542
final static int SUPERSCRIPT
Indicates superscripted text.
Definition: TextStyle.java:46
static String toLastCSV(String value)
Private function to return the value as a last element in a Comma Separated Value (CSV) format.
Definition: TextStyle.java:398
Color getFontColor()
Return the font Color for this Style.
Definition: TextStyle.java:277
This class is used for logging debug messages.
Definition: Debug.java:39
static final int INFO
Informational messages.
Definition: Debug.java:42
static void log(int flag, String msg)
Log message based on the flag type.
Definition: Debug.java:205
static final int ERROR
Error messages.
Definition: Debug.java:44
T * clone(T *const other)
Any value
@ Exception
int i
m
Provides general purpose utilities.
Provides interfaces for converting between two Document formats, and supports a "merge" interface for...
Definition: Convert.java:19
sal_Int32 attribute