コード例 #1
0
NS_IMETHODIMP
nsSVGPathGeometryFrame::UpdateCoveredRegion()
{
  mRect.Empty();

  gfxContext context(nsSVGUtils::GetThebesComputationalSurface());

  GeneratePath(&context);
  context.IdentityMatrix();

  gfxRect extent = context.GetUserPathExtent();

  // Be careful when replacing the following logic to get the fill and stroke
  // extents independently (instead of computing the stroke extents from the
  // path extents). You may think that you can just use the stroke extents if
  // there is both a fill and a stroke. In reality it's necessary to calculate
  // both the fill and stroke extents, and take the union of the two. There are
  // two reasons for this:
  //
  // # Due to stroke dashing, in certain cases the fill extents could actually
  //   extend outside the stroke extents.
  // # If the stroke is very thin, cairo won't paint any stroke, and so the
  //   stroke bounds that it will return will be empty.

  if (HasStroke()) {
    SetupCairoStrokeGeometry(&context);
    if (extent.Width() <= 0 && extent.Height() <= 0) {
      // If 'extent' is empty, its position will not be set. Although
      // GetUserStrokeExtent gets the extents wrong we can still use it
      // to get the device space position of zero length stroked paths.
      extent = context.GetUserStrokeExtent();
      extent.pos.x += extent.size.width / 2;
      extent.pos.y += extent.size.height / 2;
      extent.size.width = 0;
      extent.size.height = 0;
    }
    extent = nsSVGUtils::PathExtentsToMaxStrokeExtents(extent, this);
  } else if (GetStyleSVG()->mFill.mType == eStyleSVGPaintType_None) {
    extent = gfxRect(0, 0, 0, 0);
  }

  if (!extent.IsEmpty()) {
    mRect = nsSVGUtils::ToAppPixelRect(PresContext(), extent);
  }

  // Add in markers
  mRect = GetCoveredRegion();

  return NS_OK;
}
コード例 #2
0
PRBool
nsSVGGeometryFrame::SetupCairoStroke(gfxContext *aContext)
{
  if (!HasStroke()) {
    return PR_FALSE;
  }
  SetupCairoStrokeHitGeometry(aContext);

  const nsStyleSVG* style = GetStyleSVG();
  float opacity = MaybeOptimizeOpacity(style->mStrokeOpacity);

  nsSVGPaintServerFrame *ps =
    GetPaintServer(&style->mStroke, nsSVGEffects::StrokeProperty());
  if (ps && ps->SetupPaintServer(aContext, this, opacity))
    return PR_TRUE;

  // On failure, use the fallback colour in case we have an
  // objectBoundingBox where the width or height of the object is zero.
  // See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
  SetupFallbackOrPaintColor(aContext, GetStyleContext(),
                            &nsStyleSVG::mStroke, opacity);

  return PR_TRUE;
}
コード例 #3
0
/*
==============================================
idSWFTextInstance::CalcMaxScroll
==============================================
*/
int idSWFTextInstance::CalcMaxScroll( int numLines ) {

	if ( numLines != -1 ) {
		if ( numLines < 0 )  {
			numLines = 0;
		}
		maxscroll = numLines;
		return maxscroll;
	}

	const idSWFEditText * shape = editText;	
	if ( !( shape->flags & SWF_ET_MULTILINE ) ) {
		return 0;
	}

	if ( swf == NULL ) {
		return 0;
	}

	idSWFDictionaryEntry * fontEntry = swf->FindDictionaryEntry( shape->fontID, SWF_DICT_FONT );	
	if ( fontEntry == NULL ) {
		return 0;
	}

	idSWFFont * swfFont = fontEntry->font;
	if ( swfFont == NULL ) {
		return 0;
	}

	const idFont * fontInfo = swfFont->fontID;
	if ( fontInfo == NULL ) {
		return 0;
	}

	idStr textCheck;
	if ( variable.IsEmpty() ) {
		textCheck = idLocalization::GetString( text );
	} else {
		textCheck = idLocalization::GetString( variable );
	}

	if ( textCheck.IsEmpty() ) {
		return 0;
	}

	float x = bounds.tl.x;
	float y = bounds.tl.y;

	idList< idStr > textLines;
	idStr * currentLine = &textLines.Alloc();

	// tracks the last breakable character we found
	int lastbreak = 0;
	float lastbreakX = 0;
	int charIndex = 0;

	if ( IsSubtitle() ) {
		charIndex = GetSubStartIndex();
	}

	while ( charIndex < textCheck.Length() ) {
		if ( textCheck[ charIndex ] == '\n' ) {
			if ( shape->flags & SWF_ET_MULTILINE ) {
				currentLine->Append( '\n' );
				x = bounds.tl.x;
				y += linespacing;
				currentLine = &textLines.Alloc();			
				lastbreak = 0;
				charIndex++;
				continue;
			} else {
				break;
			}
		}
		int glyphStart = charIndex;
		uint32 tc = textCheck.UTF8Char( charIndex );
		scaledGlyphInfo_t glyph;
		fontInfo->GetScaledGlyph( glyphScale, tc, glyph );
		float glyphSkip = glyph.xSkip;
		if ( HasStroke() ) {
			glyphSkip += ( swf_textStrokeSizeGlyphSpacer.GetFloat() * GetStrokeWeight() * glyphScale );
		}

		if ( x + glyphSkip > bounds.br.x ) {
			if ( shape->flags & ( SWF_ET_MULTILINE | SWF_ET_WORDWRAP ) ) {
				if ( lastbreak > 0 ) {
					int curLineIndex = currentLine - &textLines[0];
					idStr * newline = &textLines.Alloc();
					currentLine = &textLines[ curLineIndex ];
					if ( maxLines == 1 ) {
						currentLine->CapLength( currentLine->Length() - 3 );
						currentLine->Append( "..." );
						break;
					} else {
						*newline = currentLine->c_str() + lastbreak;
						currentLine->CapLength( lastbreak );
						currentLine = newline;
						x -= lastbreakX;
					}
				} else {
					currentLine = &textLines.Alloc();
					x = bounds.tl.x;
				}
				lastbreak = 0;
			} else {
				break;
			}
		}
		while ( glyphStart < charIndex && glyphStart < text.Length() ) {
			currentLine->Append( text[ glyphStart++ ] );
		}
		x += glyphSkip;
		if ( tc == ' ' || tc == '-' ) {
			lastbreak = currentLine->Length();
			lastbreakX = x;
		}
	}
		
	maxscroll = textLines.Num() - maxLines;
	if ( maxscroll < 0 ) {
		maxscroll = 0;
	}
	return maxscroll;
}
コード例 #4
0
gfxRect
nsSVGPathGeometryFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
                                            PRUint32 aFlags)
{
  if (aToBBoxUserspace.IsSingular()) {
    // XXX ReportToConsole
    return gfxRect(0.0, 0.0, 0.0, 0.0);
  }

  nsRefPtr<gfxContext> context =
    new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());

  GeneratePath(context, &aToBBoxUserspace);
  context->IdentityMatrix();

  gfxRect bbox;

  // Be careful when replacing the following logic to get the fill and stroke
  // extents independently (instead of computing the stroke extents from the
  // path extents). You may think that you can just use the stroke extents if
  // there is both a fill and a stroke. In reality it's necessary to calculate
  // both the fill and stroke extents, and take the union of the two. There are
  // two reasons for this:
  //
  // # Due to stroke dashing, in certain cases the fill extents could actually
  //   extend outside the stroke extents.
  // # If the stroke is very thin, cairo won't paint any stroke, and so the
  //   stroke bounds that it will return will be empty.

  gfxRect pathExtents = context->GetUserPathExtent();

  // Account for fill:
  if ((aFlags & nsSVGUtils::eBBoxIncludeFill) != 0 &&
      ((aFlags & nsSVGUtils::eBBoxIgnoreFillIfNone) == 0 ||
       GetStyleSVG()->mFill.mType != eStyleSVGPaintType_None)) {
    bbox = pathExtents;
  }

  // Account for stroke:
  if ((aFlags & nsSVGUtils::eBBoxIncludeStroke) != 0 &&
      ((aFlags & nsSVGUtils::eBBoxIgnoreStrokeIfNone) == 0 || HasStroke())) {
    // We can't use context->GetUserStrokeExtent() since it doesn't work for
    // device space extents. Instead we approximate the stroke extents from
    // pathExtents using PathExtentsToMaxStrokeExtents.
    if (pathExtents.Width() <= 0 && pathExtents.Height() <= 0) {
      // We have a zero length path, but it may still have non-empty stroke
      // bounds depending on the value of stroke-linecap. We need to fix up
      // pathExtents before it can be used with PathExtentsToMaxStrokeExtents
      // though, because if pathExtents is empty, its position will not have
      // been set. Happily we can use context->GetUserStrokeExtent() to find
      // the center point of the extents even though it gets the extents wrong.
      SetupCairoStrokeGeometry(context);
      pathExtents.MoveTo(context->GetUserStrokeExtent().Center());
      pathExtents.SizeTo(0, 0);
    }
    bbox =
      bbox.Union(nsSVGUtils::PathExtentsToMaxStrokeExtents(pathExtents,
                                                           this,
                                                           aToBBoxUserspace));
  }

  // Account for markers:
  if ((aFlags & nsSVGUtils::eBBoxIncludeMarkers) != 0 &&
      static_cast<nsSVGPathGeometryElement*>(mContent)->IsMarkable()) {

    float strokeWidth = GetStrokeWidth();
    MarkerProperties properties = GetMarkerProperties(this);

    if (properties.MarkersExist()) {
      nsTArray<nsSVGMark> marks;
      static_cast<nsSVGPathGeometryElement*>(mContent)->GetMarkPoints(&marks);
      PRUint32 num = marks.Length();

      if (num) {
        nsSVGMarkerFrame *frame = properties.GetMarkerStartFrame();
        if (frame) {
          gfxRect mbbox =
            frame->GetMarkBBoxContribution(aToBBoxUserspace, aFlags, this,
                                           &marks[0], strokeWidth);
          bbox.UnionRect(bbox, mbbox);
        }

        frame = properties.GetMarkerMidFrame();
        if (frame) {
          for (PRUint32 i = 1; i < num - 1; i++) {
            gfxRect mbbox =
              frame->GetMarkBBoxContribution(aToBBoxUserspace, aFlags, this,
                                             &marks[i], strokeWidth);
            bbox.UnionRect(bbox, mbbox);
          }
        }

        frame = properties.GetMarkerEndFrame();
        if (frame) {
          gfxRect mbbox =
            frame->GetMarkBBoxContribution(aToBBoxUserspace, aFlags, this,
                                           &marks[num-1], strokeWidth);
          bbox.UnionRect(bbox, mbbox);
        }
      }
    }
  }

  return bbox;
}