Beispiel #1
0
void floatWidthMissingGlyphCallback(const TextRun& run, SVGTextRunWalkerMeasuredLengthData& data)
{
    // Handle system font fallback
    FontDescription fontDescription(data.font->fontDescription());
    fontDescription.setFamily(FontFamily());
    Font font(fontDescription, 0, 0); // spacing handled by SVG text code.
    font.update(data.font->fontSelector());

    data.length += font.floatWidth(run);
}
Beispiel #2
0
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	long _rect[4];
	GetClientRect(hWnd, (LPRECT)_rect);

	Graphics* g_p;
	POINT p;
	GetCursorPos(&p);
	Font font(&FontFamily(L"Arial"), 12);
	SolidBrush brush(Color::Black);
	Gdiplus::Rect* rect_p;

	//if (message != WM_PAINT && message != WM_KEYUP)
	//{
	//	hdc = BeginPaint(hWnd, &ps);
	//	g_p = new Graphics(hdc);
	//	rect_p = new Rect(0, 0, 10 * 10, 24);
	//	g_p->FillRectangle(new SolidBrush(Color::White), *rect_p);

	//	POINT scr;
	//	scr.x = 0;
	//	scr.y = 0;
	//	ClientToScreen(hWnd, &scr);
	//	
	//	g_p->DrawString((std::wstring(L"Freq: ")+std::to_wstring(freqdiff*(p.x-scr.x))).c_str(), -1, &font, PointF(0, 0), &brush);
	//	EndPaint(hWnd, &ps);
	//	InvalidateRect(hWnd, NULL, FALSE);
	//}

	switch (message)
	{
	case WM_SIZE:
		scrW = _rect[2] - _rect[0];
		scrH = _rect[3] - _rect[1];
		break;
	case WM_KEYUP:
		if (wParam == 0x50) isPaused = !isPaused;
		if (wParam == 0x50 - 1) w.reset();
		break;
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// Parse the menu selections:
		switch (wmId)
		{
		case IDM_ABOUT:
			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		if (!isPaused) OnPaint(hWnd, hdc);
		EndPaint(hWnd, &ps);
		InvalidateRect(hWnd, NULL, FALSE);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}
Beispiel #3
0
void Font::drawTextUsingSVGFont(GraphicsContext* context, const TextRun& run, 
                                const FloatPoint& point, int from, int to) const
{
    SVGFontElement* fontElement = 0;
    SVGFontFaceElement* fontFaceElement = 0;

    if (const SVGFontData* fontData = svgFontAndFontFaceElementForFontData(primaryFont(), fontFaceElement, fontElement)) {
        if (!fontElement)
            return;

        SVGTextRunWalkerDrawTextData data;
        FloatPoint currentPoint = point;
        float scale = convertEmUnitToPixel(size(), fontFaceElement->unitsPerEm(), 1.0f);

        SVGPaintServer* activePaintServer = run.activePaintServer();

        // If renderObject is not set, we're dealing for HTML text rendered using SVG Fonts.
        if (!run.referencingRenderObject()) {
            ASSERT(!activePaintServer);

            // TODO: We're only supporting simple filled HTML text so far.
            SVGPaintServerSolid* solidPaintServer = SVGPaintServer::sharedSolidPaintServer();
            solidPaintServer->setColor(context->fillColor());

            activePaintServer = solidPaintServer;
        }

        ASSERT(activePaintServer);

        int charsConsumed;
        String glyphName;
        bool isVerticalText = false;
        float xStartOffset = floatWidthOfSubStringUsingSVGFont(this, run, 0, run.rtl() ? to : 0, run.rtl() ? run.length() : from, charsConsumed, glyphName);
        FloatPoint glyphOrigin;

        String language;

        // TODO: language matching & svg glyphs should be possible for HTML text, too.
        if (run.referencingRenderObject()) {
            isVerticalText = isVerticalWritingMode(run.referencingRenderObject()->style()->svgStyle());    

            if (SVGElement* element = static_cast<SVGElement*>(run.referencingRenderObject()->element()))
                language = element->getAttribute(XMLNames::langAttr);
        }

        if (!isVerticalText) {
            glyphOrigin.setX(fontData->horizontalOriginX() * scale);
            glyphOrigin.setY(fontData->horizontalOriginY() * scale);
        }

        data.extraCharsAvailable = 0;
        data.charsConsumed = 0;

        SVGTextRunWalker<SVGTextRunWalkerDrawTextData> runWalker(fontData, fontElement, data, drawTextUsingSVGFontCallback, drawTextMissingGlyphCallback);
        runWalker.walk(run, isVerticalText, language, from, to);

        SVGPaintTargetType targetType = context->textDrawingMode() == cTextStroke ? ApplyToStrokeTargetType : ApplyToFillTargetType;

        unsigned numGlyphs = data.glyphIdentifiers.size();
        unsigned fallbackCharacterIndex = 0;
        for (unsigned i = 0; i < numGlyphs; ++i) {
            const SVGGlyphIdentifier& identifier = data.glyphIdentifiers[run.rtl() ? numGlyphs - i - 1 : i];
            if (identifier.isValid) {
                // FIXME: Support arbitary SVG content as glyph (currently limited to <glyph d="..."> situations).
                if (!identifier.pathData.isEmpty()) {
                    context->save();

                    if (isVerticalText) {
                        glyphOrigin.setX(identifier.verticalOriginX * scale);
                        glyphOrigin.setY(identifier.verticalOriginY * scale);
                    }

                    context->translate(xStartOffset + currentPoint.x() + glyphOrigin.x(), currentPoint.y() + glyphOrigin.y());
                    context->scale(FloatSize(scale, -scale));

                    context->beginPath();
                    context->addPath(identifier.pathData);

                    if (activePaintServer->setup(context, run.referencingRenderObject(), targetType)) {
                        // Spec: Any properties specified on a text elements which represents a length, such as the
                        // 'stroke-width' property, might produce surprising results since the length value will be
                        // processed in the coordinate system of the glyph. (TODO: What other lengths? miter-limit? dash-offset?)
                        if (targetType == ApplyToStrokeTargetType && scale != 0.0f)
                            context->setStrokeThickness(context->strokeThickness() / scale);

                        activePaintServer->renderPath(context, run.referencingRenderObject(), targetType);
                        activePaintServer->teardown(context, run.referencingRenderObject(), targetType);
                    }

                    context->restore();
                }

                if (isVerticalText)
                    currentPoint.move(0.0f, identifier.verticalAdvanceY * scale);
                else
                    currentPoint.move(identifier.horizontalAdvanceX * scale, 0.0f);
            } else {
                // Handle system font fallback
                FontDescription fontDescription(context->font().fontDescription());
                fontDescription.setFamily(FontFamily());
                Font font(fontDescription, 0, 0); // spacing handled by SVG text code.
                font.update(context->font().fontSelector());

                TextRun fallbackCharacterRun(run);
                fallbackCharacterRun.setText(&data.fallbackCharacters[run.rtl() ? data.fallbackCharacters.size() - fallbackCharacterIndex - 1 : fallbackCharacterIndex], 1);
                font.drawText(context, fallbackCharacterRun, currentPoint);

                if (isVerticalText)
                    currentPoint.move(0.0f, font.floatWidth(fallbackCharacterRun));
                else
                    currentPoint.move(font.floatWidth(fallbackCharacterRun), 0.0f);

                fallbackCharacterIndex++;
            }
        }
    }
}
Beispiel #4
0
bool Font::fromString(string const & data, bool & toggle)
{
	istringstream is(data);
	Lexer lex;
	lex.setStream(is);

	int nset = 0;
	while (lex.isOK()) {
		string token;
		if (lex.next())
			token = lex.getString();

		if (token.empty() || !lex.next())
			break;

		if (token == "family") {
			int const next = lex.getInteger();
			bits_.setFamily(FontFamily(next));

		} else if (token == "series") {
			int const next = lex.getInteger();
			bits_.setSeries(FontSeries(next));

		} else if (token == "shape") {
			int const next = lex.getInteger();
			bits_.setShape(FontShape(next));

		} else if (token == "size") {
			int const next = lex.getInteger();
			bits_.setSize(FontSize(next));

		} else if (token == "emph" || token == "underbar" ||
			   token == "noun" || token == "number" ||
			   token == "uuline" || token == "uwave" ||
			   token == "strikeout") {

			int const next = lex.getInteger();
			FontState const misc = FontState(next);

			if (token == "emph")
				bits_.setEmph(misc);
			else if (token == "underbar")
				bits_.setUnderbar(misc);
			else if (token == "strikeout")
				bits_.setStrikeout(misc);
			else if (token == "uuline")
				bits_.setUuline(misc);
			else if (token == "uwave")
				bits_.setUwave(misc);
			else if (token == "noun")
				bits_.setNoun(misc);
			else if (token == "number")
				bits_.setNumber(misc);

		} else if (token == "color") {
			int const next = lex.getInteger();
			bits_.setColor(ColorCode(next));

		/**
		} else if (token == "background") {
			int const next = lex.getInteger();
			bits_.setBackground(ColorCode(next));
		*/

		} else if (token == "language") {
			string const next = lex.getString();
			setLanguage(languages.getLanguage(next));

		} else if (token == "toggleall") {
			toggle = lex.getBool();

		} else {
			// Unrecognised token
			break;
		}

		++nset;
	}
	return (nset > 0);
}
Beispiel #5
0
/*
** This routine adds information to the input texts that doesn't change
** when the display is resized or when new fonts are selected, etc.
** Mostly this means adding style attributes.  But other constant
** information (such as numbering on <li> and images used for <IMG>)
** is also obtained.  The key is that this routine is only called
** once, where the sizer and layout routines can be called many times.
**
** This routine is called whenever the list of elements grows.  The
** style stack is stored as part of the HTML widget so that we can
** always continue where we left off the last time.
**
** In addition to adding style, this routine will invoke callbacks
** needed to acquire information about a markup.  The htmlPtr->zIsVisitied
** callback is called for each <a> and the htmlPtr->zGetImage is called
** for each <IMG> or for each <LI> that has a SRC= field.
**
** This routine may invoke a callback procedure which could delete
** the HTML widget.
**
** When a markup is inserted or deleted from the token list, the
** style routine must be completely rerun from the beginning.  So
** what we said above, that this routine is only run once, is not
** strictly true.
*/
void HtmlAddStyle(HtmlWidget *htmlPtr, HtmlElement *p){
  HtmlStyle style;          /* Current style */
  int size;                 /* A new font size */
  int i;                    /* Loop counter */
  int paraAlign;            /* Current paragraph alignment */
  int rowAlign;             /* Current table row alignment */
  int anchorFlags;          /* Flags associated with <a> tag */
  int inDt;                 /* True if within <dt>..</dt> */
  HtmlStyle nextStyle;      /* Style for next token if useNextStyle==1 */
  int useNextStyle = 0;     /* True if nextStyle is valid */
  char *z;                  /* A tag parameter's value */

  /* The size of header fonts relative to the current font size */
  static int header_sizes[] = {+2, +1, 1, 1, -1, -1};

  /* Don't allow recursion */
  if( htmlPtr->flags & STYLER_RUNNING ){ TestPoint(0); return; }
  htmlPtr->flags |= STYLER_RUNNING;

  /* Load the style state out of the htmlPtr structure and into local
  ** variables.  This is purely a matter of convenience... */
  style = GetCurrentStyle(htmlPtr);
  paraAlign = htmlPtr->paraAlignment;
  rowAlign = htmlPtr->rowAlignment;
  anchorFlags = htmlPtr->anchorFlags;
  inDt = htmlPtr->inDt;

  /* Loop over tokens */
  while( p ){
    switch( p->base.type ){
      case Html_A:
        if( htmlPtr->anchorStart ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndA);
          htmlPtr->anchorStart = 0;
          anchorFlags = 0;
        }
        z = HtmlMarkupArg(p,"href",0);
        if( z ){
          HtmlLock(htmlPtr);
          style.color = GetLinkColor(htmlPtr, z);
          if( htmlPtr->underlineLinks ){
            style.flags |= STY_Underline;
          }
          if( HtmlUnlock(htmlPtr) ) return;
          anchorFlags |= STY_Anchor;
          PushStyleStack(htmlPtr, Html_EndA, style);
          htmlPtr->anchorStart = p;
        }
        break;
      case Html_EndA:
        if( htmlPtr->anchorStart ){
          p->ref.pOther = htmlPtr->anchorStart;
          style = HtmlPopStyleStack(htmlPtr, Html_EndA);
          htmlPtr->anchorStart = 0;
          anchorFlags = 0;
        }
        break;
      case Html_ADDRESS:
      case Html_EndADDRESS:
      case Html_BLOCKQUOTE:
      case Html_EndBLOCKQUOTE:
        paraAlign = ALIGN_None;
        TestPoint(0);
        break;
      case Html_APPLET:
        if( htmlPtr->zAppletCommand && *htmlPtr->zAppletCommand ){
          nextStyle = style;
          nextStyle.flags |= STY_Invisible;
          PushStyleStack(htmlPtr, Html_EndAPPLET, nextStyle);
          useNextStyle = 1;
        }else{
          PushStyleStack(htmlPtr, Html_EndAPPLET, style);
        }
        TestPoint(0);
        break;
      case Html_B:
        style.font = BoldFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndB, style);
        TestPoint(0);
        break;
      case Html_EndAPPLET:
      case Html_EndB:
      case Html_EndBIG:
      case Html_EndCENTER:
      case Html_EndCITE:
      case Html_EndCODE:
      case Html_EndCOMMENT:
      case Html_EndEM:
      case Html_EndFONT:
      case Html_EndI:
      case Html_EndKBD:
      case Html_EndMARQUEE:
      case Html_EndNOBR:
      case Html_EndNOFRAME:
      case Html_EndNOSCRIPT:
      case Html_EndS:
      case Html_EndSAMP:
      case Html_EndSMALL:
      case Html_EndSTRIKE:
      case Html_EndSTRONG:
      case Html_EndSUB:
      case Html_EndSUP:
      case Html_EndTITLE:
      case Html_EndTT:
      case Html_EndU:
      case Html_EndVAR:
        style = HtmlPopStyleStack(htmlPtr, p->base.type);
        TestPoint(0);
        break;
      case Html_BASE:
        z = HtmlMarkupArg(p,"href",0);
        if( z ){
          HtmlLock(htmlPtr);
          z = HtmlResolveUri(htmlPtr, z);
          if( HtmlUnlock(htmlPtr) ) return;
          if( z!=0 ){
            if( htmlPtr->zBaseHref ){
              HtmlFree(htmlPtr->zBaseHref);
            }
            htmlPtr->zBaseHref = z;
          }
        }
        break;
      case Html_EndDIV:
        paraAlign = ALIGN_None;
        style = HtmlPopStyleStack(htmlPtr, p->base.type);
        TestPoint(0);
        break;
      case Html_EndBASEFONT:
        style = HtmlPopStyleStack(htmlPtr, Html_EndBASEFONT);
        style.font = FontFamily(style.font) + 2;
        TestPoint(0);
        break;
      case Html_BIG:
        ScaleFont(&style,1);
        PushStyleStack(htmlPtr, Html_EndBIG, style);
        TestPoint(0);
        break;
      case Html_CAPTION:
        paraAlign = GetAlignment(p, paraAlign);
        TestPoint(0);
        break;
      case Html_EndCAPTION:
        paraAlign = ALIGN_None;
        TestPoint(0);
        break;
      case Html_CENTER:
        paraAlign = ALIGN_None;
        style.align = ALIGN_Center;
        PushStyleStack(htmlPtr, Html_EndCENTER, style);
        TestPoint(0);
        break;
      case Html_CITE:
        PushStyleStack(htmlPtr, Html_EndCITE, style);
        TestPoint(0);
        break;
      case Html_CODE:
        style.font = CWFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndCODE, style);
        TestPoint(0);
        break;
      case Html_COMMENT:
        style.flags |= STY_Invisible;
        PushStyleStack(htmlPtr, Html_EndCOMMENT, style);
        TestPoint(0);
        break;
      case Html_DD:
        if( htmlPtr->innerList && htmlPtr->innerList->base.type==Html_DL ){
          p->ref.pOther = htmlPtr->innerList;
          TestPoint(0);
        }else{
          p->ref.pOther = 0;
          TestPoint(0);
        }
        inDt = 0;
        break;
      case Html_DIR:
      case Html_MENU:
      case Html_UL:
        p->list.pPrev = htmlPtr->innerList;
        p->list.cnt = 0;
        htmlPtr->innerList = p;
        if( p->list.pPrev==0 ){
          p->list.type = LI_TYPE_Bullet1;
          p->list.compact = HtmlMarkupArg(p,"compact",0)!=0;
          TestPoint(0);
        }else if( p->list.pPrev->list.pPrev==0 ){
          p->list.type = LI_TYPE_Bullet2;
          p->list.compact = 1;
          TestPoint(0);
        }else{
          p->list.type = LI_TYPE_Bullet3;
          p->list.compact = 1;
          TestPoint(0);
        }
        p->list.type = GetUnorderedListType(p,p->list.type);
        break;
      case Html_EndDL:
        inDt = 0;
        TestPoint(0);
        /* Fall thru into the next case */
      case Html_EndDIR:
      case Html_EndMENU:
      case Html_EndOL:
      case Html_EndUL:
        p->ref.pOther = htmlPtr->innerList;
        if( htmlPtr->innerList ){
          htmlPtr->innerList = htmlPtr->innerList->list.pPrev;
          TestPoint(0);
        }else{
          TestPoint(0);
        }
        break;
      case Html_DIV:
        paraAlign = ALIGN_None;
        style.align = GetAlignment(p, style.align);
        PushStyleStack(htmlPtr, Html_EndDIV, style);
        TestPoint(0);
        break;
      case Html_DT:
        if( htmlPtr->innerList && htmlPtr->innerList->base.type==Html_DL ){
          p->ref.pOther = htmlPtr->innerList;
          TestPoint(0);
        }else{
          p->ref.pOther = 0;
          TestPoint(0);
        }
        inDt = STY_DT;
        break;
      case Html_EndDD:
      case Html_EndDT:
        inDt = 0;
        TestPoint(0);
        break;
      case Html_DL:
        p->list.pPrev = htmlPtr->innerList;
        p->list.cnt = 0;
        htmlPtr->innerList = p;
        p->list.compact = HtmlMarkupArg(p,"compact",0)!=0;
        inDt = 0;
        TestPoint(0);
        break;
      case Html_EM:
        style.font = ItalicFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndEM, style);
        TestPoint(0);
        break;
      case Html_EMBED:
        break;
      case Html_BASEFONT:
      case Html_FONT:
        z = HtmlMarkupArg(p,"size",0);
        if( z ){
          if( *z=='-' ){
            size = FontSize(style.font) - atoi(&z[1]);
          }else if( *z=='+' ){
            size = FontSize(style.font) + atoi(&z[1]);
          }else{
            size = atoi(z);
          }
          if( size <= 0 ){
            size = 1;
          }
          if( size >= N_FONT_SIZE ){
            size = N_FONT_SIZE - 1;
          }
          style.font = FontFamily(style.font) + size - 1;
        }
        z = HtmlMarkupArg(p,"color",0);
        if( z ){
          style.color = HtmlGetColorByName(htmlPtr, z);
        }
        PushStyleStack(htmlPtr,
            p->base.type==Html_FONT ? Html_EndFONT : Html_EndBASEFONT, style);
        break;
      case Html_FORM: {
        char *zUrl;
        char *zMethod;
        Tcl_DString cmd;      /* -formcommand callback */
        int result;
        char zToken[50];

        htmlPtr->formStart = 0;
        p->form.id = 0;
        if( htmlPtr->zFormCommand==0 || htmlPtr->zFormCommand[0]==0 ){
          TestPoint(0);
          break;
        }
        zUrl = HtmlMarkupArg(p,"action",0);
        if( zUrl==0 ){
          TestPoint(0);
          break;
        }
        HtmlLock(htmlPtr);
        zUrl = HtmlResolveUri(htmlPtr, zUrl);
        if( HtmlUnlock(htmlPtr) ) return;
        if( zUrl==0 ) break;
        zMethod = HtmlMarkupArg(p,"method","GET");
        sprintf(zToken," %d form ", ++htmlPtr->nForm);
        Tcl_DStringInit(&cmd);
        Tcl_DStringAppend(&cmd, htmlPtr->zFormCommand, -1);
        Tcl_DStringAppend(&cmd, zToken, -1);
        Tcl_DStringAppendElement(&cmd, zUrl);
        HtmlFree(zUrl);
        Tcl_DStringAppendElement(&cmd, zMethod);
        Tcl_DStringStartSublist(&cmd);
        HtmlAppendArglist(&cmd, p);
        Tcl_DStringEndSublist(&cmd);
        HtmlLock(htmlPtr);
        result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd));
        Tcl_DStringFree(&cmd);
        if( HtmlUnlock(htmlPtr) ) return;
        if( result==TCL_OK ){
          htmlPtr->formStart = p;
          p->form.id = htmlPtr->nForm;
        }
        Tcl_ResetResult(htmlPtr->interp);
        break;
      }
      case Html_EndFORM:
        p->ref.pOther = htmlPtr->formStart;
        htmlPtr->formStart = 0;
        TestPoint(0);
        break;
      case Html_H1:
      case Html_H2:
      case Html_H3:
      case Html_H4:
      case Html_H5:
      case Html_H6:
        paraAlign = ALIGN_None;
        i = (p->base.type - Html_H1)/2 + 1;
        if( i>=1 && i<=6 ){
          ScaleFont(&style,header_sizes[i-1]);
        }
        style.font = BoldFont( FontSize(style.font) );
        style.align = GetAlignment(p, style.align);
        PushStyleStack(htmlPtr, Html_EndH1, style);
        break;
      case Html_EndH1:
      case Html_EndH2:
      case Html_EndH3:
      case Html_EndH4:
      case Html_EndH5:
      case Html_EndH6:
        paraAlign = ALIGN_None;
        style = HtmlPopStyleStack(htmlPtr, Html_EndH1);
        TestPoint(0);
        break;
      case Html_HR:
        nextStyle = style;
        style.align = GetAlignment(p, ALIGN_None);
        useNextStyle = 1;
        break;
      case Html_I:
        style.font = ItalicFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndI, style);
        TestPoint(0);
        break;
      case Html_IMG:
        HtmlLock(htmlPtr);
        p->image.pImage = HtmlGetImage(htmlPtr, p);
        if( HtmlUnlock(htmlPtr) ) return;
        TestPoint(0);
        break;
      case Html_INPUT:
        p->input.pForm = htmlPtr->formStart;
        TestPoint(0);
        break;
      case Html_KBD:
        style.font = CWFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndKBD, style);
        TestPoint(0);
        break;
      case Html_LI:
        if( htmlPtr->innerList ){
          p->li.type = htmlPtr->innerList->list.type;
          if( htmlPtr->innerList->base.type==Html_OL ){
            z = HtmlMarkupArg(p, "value", 0);
            if( z ){
              int n = atoi(z);
              if( n>0 ){
                p->li.cnt = n;
                htmlPtr->innerList->list.cnt = n+1;
                TestPoint(0);
              }else{
                TestPoint(0);
              }
            }else{
              p->li.cnt = htmlPtr->innerList->list.cnt++;
              TestPoint(0);
            }
            p->li.type = GetOrderedListType(p,p->li.type);
          }else{
            p->li.type = GetUnorderedListType(p,p->li.type);
            TestPoint(0);
          }
        }else{
          p->base.flags &= ~HTML_Visible;
          TestPoint(0);
        }
        break;
      case Html_MARQUEE:
        style.flags |= STY_Invisible;
        PushStyleStack(htmlPtr, Html_EndMARQUEE, style);
        TestPoint(0);
        break;
      case Html_NOBR:
        style.flags |= STY_NoBreak;
        PushStyleStack(htmlPtr, Html_EndNOBR, style);
        TestPoint(0);
        break;
      case Html_NOFRAME:
        if( htmlPtr->zFrameCommand && *htmlPtr->zFrameCommand ){
          nextStyle = style;
          nextStyle.flags |= STY_Invisible;
          PushStyleStack(htmlPtr, Html_EndNOFRAME, nextStyle);
          useNextStyle = 1;
        }else{
          PushStyleStack(htmlPtr, Html_EndNOFRAME, style);
        }
        TestPoint(0);
        break;
      case Html_NOSCRIPT:
        if( htmlPtr->zScriptCommand && *htmlPtr->zScriptCommand ){
          nextStyle = style;
          nextStyle.flags |= STY_Invisible;
          PushStyleStack(htmlPtr, Html_EndNOSCRIPT, nextStyle);
          useNextStyle = 1;
        }else{
          PushStyleStack(htmlPtr, Html_EndNOSCRIPT, style);
        }
        TestPoint(0);
        break;
      case Html_OL:
        p->list.pPrev = htmlPtr->innerList;
        p->list.type = GetOrderedListType(p,LI_TYPE_Enum_1);
        p->list.cnt = 1;
        z = HtmlMarkupArg(p,"start",0);
        if( z ){
          int n = atoi(z);
          if( n>0 ){
            p->list.cnt = n;
            TestPoint(0);
          }else{
            TestPoint(0);
          }
        }else{
          TestPoint(0);
        }
        p->list.compact = htmlPtr->innerList!=0 ||
                          HtmlMarkupArg(p,"compact",0)!=0;
        htmlPtr->innerList = p;
        break;
      case Html_P:
        paraAlign = GetAlignment(p, ALIGN_None);
        TestPoint(0);
        break;
      case Html_EndP:
        paraAlign = ALIGN_None;
        TestPoint(0);
        break;
      case Html_PRE:
      case Html_LISTING:
      case Html_XMP:
      case Html_PLAINTEXT:
        paraAlign = ALIGN_None;
        style.font = CWFont( FontSize(style.font) );
        style.flags |= STY_Preformatted;
        PushStyleStack(htmlPtr, Html_EndPRE, style);
        TestPoint(0);
        break;
      case Html_EndPRE:
      case Html_EndLISTING:
      case Html_EndXMP:
        style = HtmlPopStyleStack(htmlPtr, Html_EndPRE);
        TestPoint(0);
        break;
      case Html_S:
        style.flags |= STY_StrikeThru;
        PushStyleStack(htmlPtr, Html_EndS, style);
        TestPoint(0);
        break;
      case Html_SCRIPT:
        if( htmlPtr->zScriptCommand && *htmlPtr->zScriptCommand ){
          Tcl_DString cmd;
          int result;
          Tcl_DStringInit(&cmd);
          Tcl_DStringAppend(&cmd, htmlPtr->zScriptCommand, -1);
          Tcl_DStringStartSublist(&cmd);
          HtmlAppendArglist(&cmd, p);
          Tcl_DStringEndSublist(&cmd);
          Tcl_DStringStartSublist(&cmd);
          Tcl_DStringAppend(&cmd, p->script.zScript, p->script.nScript);
          Tcl_DStringEndSublist(&cmd);
          HtmlLock(htmlPtr);
          result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd));
          Tcl_DStringFree(&cmd);
          if( HtmlUnlock(htmlPtr) ) return;
          Tcl_ResetResult(htmlPtr->interp);
        }
        nextStyle = style;
        style.flags |= STY_Invisible;
        useNextStyle = 1;
        break;
      case Html_SELECT:
        p->input.pForm = htmlPtr->formStart;
        nextStyle.flags |= STY_Invisible;
        useNextStyle = 1;
        PushStyleStack(htmlPtr, Html_EndSELECT, style);
        htmlPtr->formElemStart = p;
        break;
      case Html_EndSELECT:
        style = HtmlPopStyleStack(htmlPtr, Html_EndSELECT);
        if( htmlPtr->formElemStart
        && htmlPtr->formElemStart->base.type==Html_SELECT ){
          p->ref.pOther = htmlPtr->formElemStart;
          MakeInvisible(p->ref.pOther, p);
        }else{
          p->ref.pOther = 0;
        }
        htmlPtr->formElemStart = 0;
        break;
      case Html_STRIKE:
        style.flags |= STY_StrikeThru;
        PushStyleStack(htmlPtr, Html_EndSTRIKE, style);
        TestPoint(0);
        break;
      case Html_STYLE:
        /* Ignore style sheets */
        break;
      case Html_SAMP:
        style.font = CWFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndSAMP, style);
        TestPoint(0);
        break;
      case Html_SMALL:
        ScaleFont(&style,-1);
        PushStyleStack(htmlPtr, Html_EndSMALL, style);
        TestPoint(0);
        break;
      case Html_STRONG:
        style.font = BoldFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndSTRONG, style);
        TestPoint(0);
        break;
      case Html_SUB:
        ScaleFont(&style,-1);
        if( style.subscript > -6 ){
          style.subscript--;
          TestPoint(0);
        }else{
          TestPoint(0);
        }
        PushStyleStack(htmlPtr, Html_EndSUB, style);
        break;
      case Html_SUP:
        ScaleFont(&style,-1);
        if( style.subscript < 6 ){
          style.subscript++;
          TestPoint(0);
        }else{
          TestPoint(0);
        }
        PushStyleStack(htmlPtr, Html_EndSUP, style);
        break;
      case Html_TABLE:
        paraAlign = ALIGN_None;
        nextStyle = style;
        nextStyle.align = ALIGN_Left;
        z = HtmlMarkupArg(p, "bgcolor", 0);
        if( z ){
          nextStyle.bgcolor = HtmlGetColorByName(htmlPtr, z);
          style.bgcolor = nextStyle.bgcolor;
/*        }else{
          nextStyle.bgcolor = COLOR_Background; */
        }
        PushStyleStack(htmlPtr, Html_EndTABLE, nextStyle);
        useNextStyle = 1;
        htmlPtr->inTd = 0;
        htmlPtr->inTr = 0;
        TestPoint(0);
        break;
      case Html_EndTABLE:
        paraAlign = ALIGN_None;
        if( htmlPtr->inTd ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndTD);
          htmlPtr->inTd = 0;
        }
        if( htmlPtr->inTr ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndTR);
          htmlPtr->inTr = 0;
        }
        style = HtmlPopStyleStack(htmlPtr, p->base.type);
        TestPoint(0);
        break;
      case Html_TD:
        if( htmlPtr->inTd ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndTD);
        }
        htmlPtr->inTd = 1;
        paraAlign = GetAlignment(p, rowAlign);
        if( (z = HtmlMarkupArg(p, "bgcolor", 0))!=0 ){
          style.bgcolor = HtmlGetColorByName(htmlPtr, z);
        }
        PushStyleStack(htmlPtr, Html_EndTD, style);
        TestPoint(0);
        break;
      case Html_TEXTAREA:
        p->input.pForm = htmlPtr->formStart;
        nextStyle = style;
        nextStyle.flags |= STY_Invisible;
        PushStyleStack(htmlPtr, Html_EndTEXTAREA, nextStyle);
        htmlPtr->formElemStart = p;
        useNextStyle = 1;
        TestPoint(0);
        break;
      case Html_EndTEXTAREA:
        style = HtmlPopStyleStack(htmlPtr, Html_EndTEXTAREA);
        if( htmlPtr->formElemStart
        && htmlPtr->formElemStart->base.type==Html_TEXTAREA ){
          p->ref.pOther = htmlPtr->formElemStart;
        }else{
          p->ref.pOther = 0;
        }
        htmlPtr->formElemStart = 0;
        break;
      case Html_TH:
        /* paraAlign = GetAlignment(p, rowAlign); */
        if( htmlPtr->inTd ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndTD);
        }
        paraAlign = GetAlignment(p, ALIGN_Center);
        style.font = BoldFont( FontSize(style.font) );
        if( (z = HtmlMarkupArg(p, "bgcolor", 0))!=0 ){
          style.bgcolor = HtmlGetColorByName(htmlPtr, z);
        }
        PushStyleStack(htmlPtr, Html_EndTD, style);
        htmlPtr->inTd = 1;
        TestPoint(0);
        break;
      case Html_TR:
        if( htmlPtr->inTd ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndTD);
          htmlPtr->inTd = 0;
        }
        if( htmlPtr->inTr ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndTR);
        }
        rowAlign = GetAlignment(p, ALIGN_None);
        if( (z = HtmlMarkupArg(p, "bgcolor", 0))!=0 ){
          style.bgcolor = HtmlGetColorByName(htmlPtr, z);
        }
        PushStyleStack(htmlPtr, Html_EndTR, style);
        htmlPtr->inTr = 1;
        TestPoint(0);
        break;
      case Html_EndTR:
        if( htmlPtr->inTd ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndTD);
          htmlPtr->inTd = 0;
        }
        style = HtmlPopStyleStack(htmlPtr, Html_EndTR);
        htmlPtr->inTr = 0;
        paraAlign = ALIGN_None;
        rowAlign = ALIGN_None;
        TestPoint(0);
        break;
      case Html_EndTD:
      case Html_EndTH:
        style = HtmlPopStyleStack(htmlPtr, Html_EndTD);
        htmlPtr->inTd = 0;
        paraAlign = ALIGN_None;
        rowAlign = ALIGN_None;
        TestPoint(0);
        break;
      case Html_TITLE:
        style.flags |= STY_Invisible;
        PushStyleStack(htmlPtr, Html_EndTITLE, style);
        TestPoint(0);
        break;
      case Html_TT:
        style.font = CWFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndTT, style);
        TestPoint(0);
        break;
      case Html_U:
        style.flags |= STY_Underline;
        PushStyleStack(htmlPtr, Html_EndU, style);
        break;
      case Html_VAR:
        style.font = ItalicFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndVAR, style);
        TestPoint(0);
        break;
      default:
        TestPoint(0);
        break;
    }
    p->base.style = style;
    p->base.style.flags |= anchorFlags | inDt;
    if( paraAlign!=ALIGN_None ){
      p->base.style.align = paraAlign;
    }
    if( useNextStyle ){
      style = nextStyle;
      useNextStyle = 0;
    }
    TRACE(HtmlTrace_Style,
      ("Style of 0x%08x font=%02d color=%02d bg=%02d "
       "align=%d flags=0x%04x token=%s\n",
      (int)p, p->base.style.font, p->base.style.color, p->base.style.bgcolor,
      p->base.style.align, p->base.style.flags, HtmlTokenName(p)));
    p = p->pNext;
  }

  /* Copy state information back into the htmlPtr structure for
  ** safe keeping. */
  htmlPtr->paraAlignment = paraAlign;
  htmlPtr->rowAlignment = rowAlign;
  htmlPtr->anchorFlags = anchorFlags;
  htmlPtr->inDt = inDt;
  htmlPtr->flags &= ~STYLER_RUNNING;
}
void
AnnotationObject::SetFromNode(DataNode *parentNode)
{
    if(parentNode == 0)
        return;

    DataNode *searchNode = parentNode->GetNode("AnnotationObject");
    if(searchNode == 0)
        return;

    DataNode *node;
    if((node = searchNode->GetNode("objectName")) != 0)
        SetObjectName(node->AsString());
    if((node = searchNode->GetNode("objectType")) != 0)
    {
        // Allow enums to be int or string in the config file
        if(node->GetNodeType() == INT_NODE)
        {
            int ival = node->AsInt();
            if(ival >= 0 && ival < 8)
                SetObjectType(AnnotationType(ival));
        }
        else if(node->GetNodeType() == STRING_NODE)
        {
            AnnotationType value;
            if(AnnotationType_FromString(node->AsString(), value))
                SetObjectType(value);
        }
    }
    if((node = searchNode->GetNode("visible")) != 0)
        SetVisible(node->AsBool());
    if((node = searchNode->GetNode("active")) != 0)
        SetActive(node->AsBool());
    if((node = searchNode->GetNode("position")) != 0)
    {
        if(node->GetNodeType() == FLOAT_ARRAY_NODE)
        {
            const float *fn = node->AsFloatArray();
            double dp[3] = {fn[0], fn[1], fn[2]};
            SetPosition(dp);
        }
        else
            SetPosition(node->AsDoubleArray());
    }
    if((node = searchNode->GetNode("position2")) != 0)
    {
        if(node->GetNodeType() == FLOAT_ARRAY_NODE)
        {
            const float *fn = node->AsFloatArray();
            double dp[3] = {fn[0], fn[1], fn[2]};
            SetPosition2(dp);
        }
        else
            SetPosition2(node->AsDoubleArray());
    }
    if((node = searchNode->GetNode("textColor")) != 0)
        textColor.SetFromNode(node);
    if((node = searchNode->GetNode("useForegroundForTextColor")) != 0)
        SetUseForegroundForTextColor(node->AsBool());
    if((node = searchNode->GetNode("color1")) != 0)
        color1.SetFromNode(node);
    if((node = searchNode->GetNode("color2")) != 0)
        color2.SetFromNode(node);
    if((node = searchNode->GetNode("text")) != 0)
        SetText(node->AsStringVector());
    if((node = searchNode->GetNode("fontFamily")) != 0)
    {
        // Allow enums to be int or string in the config file
        if(node->GetNodeType() == INT_NODE)
        {
            int ival = node->AsInt();
            if(ival >= 0 && ival < 3)
                SetFontFamily(FontFamily(ival));
        }
        else if(node->GetNodeType() == STRING_NODE)
        {
            FontFamily value;
            if(FontFamily_FromString(node->AsString(), value))
                SetFontFamily(value);
        }
    }
    if((node = searchNode->GetNode("fontBold")) != 0)
        SetFontBold(node->AsBool());
    if((node = searchNode->GetNode("fontItalic")) != 0)
        SetFontItalic(node->AsBool());
    if((node = searchNode->GetNode("fontShadow")) != 0)
        SetFontShadow(node->AsBool());
    if((node = searchNode->GetNode("floatAttribute1")) != 0)
        SetDoubleAttribute1(node->AsDouble());
    if((node = searchNode->GetNode("doubleAttribute1")) != 0)
        SetDoubleAttribute1(node->AsDouble());
    if((node = searchNode->GetNode("intAttribute1")) != 0)
        SetIntAttribute1(node->AsInt());
    if((node = searchNode->GetNode("intAttribute2")) != 0)
        SetIntAttribute2(node->AsInt());
    if((node = searchNode->GetNode("intAttribute3")) != 0)
        SetIntAttribute3(node->AsInt());
    if((node = searchNode->GetNode("doubleVector1")) != 0)
        SetDoubleVector1(node->AsDoubleVector());
    if((node = searchNode->GetNode("stringVector1")) != 0)
        SetStringVector1(node->AsStringVector());
    if((node = searchNode->GetNode("stringVector2")) != 0)
        SetStringVector2(node->AsStringVector());
}
AnnotationObject::FontFamily
AnnotationObject::GetFontFamily() const
{
    return FontFamily(fontFamily);
}