private void setSyntaxTheme(int tokenType, String id) {
    Style style = getSyntaxScheme().getStyle(tokenType);

    Map<String, Object> styledFont = processing.app.Theme.getStyledFont(id, style.font);
    style.foreground = (Color) styledFont.get("color");
    style.font = (Font) styledFont.get("font");

    getSyntaxScheme().setStyle(tokenType, style);
  }
  public TimedTextObject parseFile(String fileName, InputStream is)
      throws IOException, FatalParsingException {

    TimedTextObject tto = new TimedTextObject();
    tto.fileName = fileName;

    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder;
    try {
      dBuilder = dbFactory.newDocumentBuilder();
      Document doc = dBuilder.parse(is);
      doc.getDocumentElement().normalize();

      // we recover the metadata
      Node node = doc.getElementsByTagName("ttm:title").item(0);
      if (node != null) tto.title = node.getTextContent();
      node = doc.getElementsByTagName("ttm:copyright").item(0);
      if (node != null) tto.copyrigth = node.getTextContent();
      node = doc.getElementsByTagName("ttm:desc").item(0);
      if (node != null) tto.description = node.getTextContent();

      // we recover the styles
      NodeList styleN = doc.getElementsByTagName("style");
      // we recover the timed text elements
      NodeList captionsN = doc.getElementsByTagName("p");
      // regions of the layout could also be recovered this way

      tto.warnings +=
          "Styling attributes are only recognized inside a style definition, to be referenced later in the captions.\n\n";
      // we parse the styles
      for (int i = 0; i < styleN.getLength(); i++) {
        Style style = new Style(Style.defaultID());
        node = styleN.item(i);
        NamedNodeMap attr = node.getAttributes();
        // we get the id
        Node currentAtr = attr.getNamedItem("id");
        if (currentAtr != null) style.iD = currentAtr.getNodeValue();
        currentAtr = attr.getNamedItem("xml:id");
        if (currentAtr != null) style.iD = currentAtr.getNodeValue();

        // we get the style it may be based upon
        currentAtr = attr.getNamedItem("style");
        if (currentAtr != null)
          if (tto.styling.containsKey(currentAtr.getNodeValue()))
            style = new Style(style.iD, tto.styling.get(currentAtr.getNodeValue()));

        // we check for background color
        currentAtr = attr.getNamedItem("tts:backgroundColor");
        if (currentAtr != null) style.backgroundColor = parseColor(currentAtr.getNodeValue(), tto);

        // we check for color
        currentAtr = attr.getNamedItem("tts:color");
        if (currentAtr != null) style.color = parseColor(currentAtr.getNodeValue(), tto);

        // we check for font family
        currentAtr = attr.getNamedItem("tts:fontFamily");
        if (currentAtr != null) style.font = currentAtr.getNodeValue();

        // we check for font size
        currentAtr = attr.getNamedItem("tts:fontSize");
        if (currentAtr != null) style.fontSize = currentAtr.getNodeValue();

        // we check for italics
        currentAtr = attr.getNamedItem("tts:fontStyle");
        if (currentAtr != null)
          if (currentAtr.getNodeValue().equalsIgnoreCase("italic")
              || currentAtr.getNodeValue().equalsIgnoreCase("oblique")) style.italic = true;
          else if (currentAtr.getNodeValue().equalsIgnoreCase("normal")) style.italic = false;

        // we check for bold
        currentAtr = attr.getNamedItem("tts:fontWeight");
        if (currentAtr != null)
          if (currentAtr.getNodeValue().equalsIgnoreCase("bold")) style.bold = true;
          else if (currentAtr.getNodeValue().equalsIgnoreCase("normal")) style.bold = false;

        // we check opacity (to set the alpha)
        currentAtr = attr.getNamedItem("tts:opacity");
        if (currentAtr != null) {
          try {
            // a number between 1.0 and 0
            float alpha = Float.parseFloat(currentAtr.getNodeValue());
            if (alpha > 1) alpha = 1;
            else if (alpha < 0) alpha = 0;

            String aa = Integer.toHexString((int) (alpha * 255));
            if (aa.length() < 2) aa = "0" + aa;

            style.color = style.color.substring(0, 6) + aa;
            style.backgroundColor = style.backgroundColor.substring(0, 6) + aa;

          } catch (NumberFormatException e) {
            // ignore the alpha
          }
        }

        // we check for text align
        currentAtr = attr.getNamedItem("tts:textAlign");
        if (currentAtr != null)
          if (currentAtr.getNodeValue().equalsIgnoreCase("left")
              || currentAtr.getNodeValue().equalsIgnoreCase("start"))
            style.textAlign = "bottom-left";
          else if (currentAtr.getNodeValue().equalsIgnoreCase("right")
              || currentAtr.getNodeValue().equalsIgnoreCase("end"))
            style.textAlign = "bottom-right";

        // we check for underline
        currentAtr = attr.getNamedItem("tts:textDecoration");
        if (currentAtr != null)
          if (currentAtr.getNodeValue().equalsIgnoreCase("underline")) style.underline = true;
          else if (currentAtr.getNodeValue().equalsIgnoreCase("noUnderline"))
            style.underline = false;

        // we add the style
        tto.styling.put(style.iD, style);
      }

      // we parse the captions
      for (int i = 0; i < captionsN.getLength(); i++) {
        Caption caption = new Caption();
        caption.content = "";
        boolean validCaption = true;
        node = captionsN.item(i);

        NamedNodeMap attr = node.getAttributes();
        // we get the begin time
        Node currentAtr = attr.getNamedItem("begin");
        // if no begin is present, 0 is assumed
        caption.start = new Time("", "");
        caption.end = new Time("", "");
        if (currentAtr != null)
          caption.start.mseconds = parseTimeExpression(currentAtr.getNodeValue(), tto, doc);

        // we get the end time, if present, duration is ignored, otherwise end is calculated from
        // duration
        currentAtr = attr.getNamedItem("end");
        if (currentAtr != null)
          caption.end.mseconds = parseTimeExpression(currentAtr.getNodeValue(), tto, doc);
        else {
          currentAtr = attr.getNamedItem("dur");
          if (currentAtr != null)
            caption.end.mseconds =
                caption.start.mseconds + parseTimeExpression(currentAtr.getNodeValue(), tto, doc);
          else
            // no end or duration, invalid format, caption is discarded
            validCaption = false;
        }

        // we get the style
        currentAtr = attr.getNamedItem("style");
        if (currentAtr != null) {
          Style style = tto.styling.get(currentAtr.getNodeValue());
          if (style != null) caption.style = style;
          else
            // unrecognized style
            tto.warnings += "unrecoginzed style referenced: " + currentAtr.getNodeValue() + "\n\n";
        }

        // we save the text
        NodeList textN = node.getChildNodes();
        for (int j = 0; j < textN.getLength(); j++) {
          if (textN.item(j).getNodeName().equals("#text"))
            caption.content += textN.item(j).getTextContent().trim();
          else if (textN.item(j).getNodeName().equals("br")) caption.content += "<br />";
        }
        // is this check worth it?
        if (caption.content.replaceAll("<br />", "").trim().isEmpty()) validCaption = false;

        // and save the caption
        if (validCaption) {
          int key = caption.start.mseconds;
          // in case the key is already there, we increase it by a millisecond, since no duplicates
          // are allowed
          while (tto.captions.containsKey(key)) key++;
          tto.captions.put(key, caption);
        }
      }

    } catch (Exception e) {
      e.printStackTrace();
      // this could be a fatal error...
      throw new FatalParsingException("Error during parsing: " + e.getMessage());
    }

    tto.built = true;
    return tto;
  }