mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-29 18:18:27 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1158090 - Fix documentation for nsDisplayListBuilder constructor. r=roc (773b76e1b3) - Bug 1153510 - Improve handling of vertical writing mode in SVG text frames. r=longsonr (bd513aa02e) - Bug 1156366 - Support vertical writing modes and upright/sideways gly# ph orientation in SVG text-on-a-path. r=longsonr (325c3c2e00) - Bug 1157951 patch 1 - Rename fields and variables in nsCharClipDisplayItem etc using VisIStart/End instead of left/right. r=roc (bc4aa0e75a) - Fix nsDisplayCanvasBackgroundColor to invalidate on color changes. (bug 1205970 part 1, r=mattwoodrow) (e51b8489a6) - Bug 1151663 - Initialize display list builder flags earlier in nsLayoutUtils::PaintFrame(). r=tn (fb55eaf2d8) - Remove willFlushRetainedLayers, which is superceded by DLBI. (bug 1205970 part 2, r=mattwoodrow) (0651277211) - Bug 1166301 - Layerize background images fixed to child elements. r=mattwoodrow (fb979f8c89) - Bug 1166301 - If APZ is enabled, only clip fixed background images to the viewport area. r=mattwoodrow (96944fa488) - Bug 885515 - Part 1: Add an analysis for detecting non-heap allocations of MOZ_HEAP_CLASS, r=ehsan (b1c53befae) - Bug 1192271 - Add helper method CustomTypeAnnotation::reportErrorIfAbsent to clang-plugin, r=ehsan (627b9d0c4c) - Bug 1195960 - Correct naming of CustomTypeAnnotation::reportErrorIfAbsent, r=me (cdba688d80)
This commit is contained in:
@@ -256,6 +256,15 @@ public:
|
||||
}
|
||||
void dumpAnnotationReason(DiagnosticsEngine &Diag, QualType T, SourceLocation Loc);
|
||||
|
||||
void reportErrorIfPresent(DiagnosticsEngine &Diag, QualType T, SourceLocation Loc,
|
||||
unsigned ErrorID, unsigned NoteID) {
|
||||
if (hasEffectiveAnnotation(T)) {
|
||||
Diag.Report(Loc, ErrorID) << T;
|
||||
Diag.Report(Loc, NoteID);
|
||||
dumpAnnotationReason(Diag, T, Loc);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool hasLiteralAnnotation(QualType T) const;
|
||||
AnnotationReason directAnnotationReason(QualType T);
|
||||
@@ -267,6 +276,8 @@ static CustomTypeAnnotation GlobalClass =
|
||||
CustomTypeAnnotation("moz_global_class", "global");
|
||||
static CustomTypeAnnotation NonHeapClass =
|
||||
CustomTypeAnnotation("moz_nonheap_class", "non-heap");
|
||||
static CustomTypeAnnotation HeapClass =
|
||||
CustomTypeAnnotation("moz_heap_class", "heap");
|
||||
static CustomTypeAnnotation MustUse =
|
||||
CustomTypeAnnotation("moz_must_use", "must-use");
|
||||
|
||||
@@ -1111,45 +1122,24 @@ void DiagnosticsMatcher::ScopeChecker::run(
|
||||
return;
|
||||
|
||||
case AV_Global:
|
||||
if (StackClass.hasEffectiveAnnotation(T)) {
|
||||
Diag.Report(Loc, StackID) << T;
|
||||
Diag.Report(Loc, GlobalNoteID);
|
||||
StackClass.dumpAnnotationReason(Diag, T, Loc);
|
||||
}
|
||||
StackClass.reportErrorIfPresent(Diag, T, Loc, StackID, GlobalNoteID);
|
||||
HeapClass.reportErrorIfPresent(Diag, T, Loc, HeapID, GlobalNoteID);
|
||||
break;
|
||||
|
||||
case AV_Automatic:
|
||||
if (GlobalClass.hasEffectiveAnnotation(T)) {
|
||||
Diag.Report(Loc, GlobalID) << T;
|
||||
Diag.Report(Loc, StackNoteID);
|
||||
GlobalClass.dumpAnnotationReason(Diag, T, Loc);
|
||||
}
|
||||
GlobalClass.reportErrorIfPresent(Diag, T, Loc, GlobalID, StackNoteID);
|
||||
HeapClass.reportErrorIfPresent(Diag, T, Loc, HeapID, StackNoteID);
|
||||
break;
|
||||
|
||||
case AV_Temporary:
|
||||
if (GlobalClass.hasEffectiveAnnotation(T)) {
|
||||
Diag.Report(Loc, GlobalID) << T;
|
||||
Diag.Report(Loc, TemporaryNoteID);
|
||||
GlobalClass.dumpAnnotationReason(Diag, T, Loc);
|
||||
}
|
||||
GlobalClass.reportErrorIfPresent(Diag, T, Loc, GlobalID, TemporaryNoteID);
|
||||
HeapClass.reportErrorIfPresent(Diag, T, Loc, HeapID, TemporaryNoteID);
|
||||
break;
|
||||
|
||||
case AV_Heap:
|
||||
if (GlobalClass.hasEffectiveAnnotation(T)) {
|
||||
Diag.Report(Loc, GlobalID) << T;
|
||||
Diag.Report(Loc, HeapNoteID);
|
||||
GlobalClass.dumpAnnotationReason(Diag, T, Loc);
|
||||
}
|
||||
if (StackClass.hasEffectiveAnnotation(T)) {
|
||||
Diag.Report(Loc, StackID) << T;
|
||||
Diag.Report(Loc, HeapNoteID);
|
||||
StackClass.dumpAnnotationReason(Diag, T, Loc);
|
||||
}
|
||||
if (NonHeapClass.hasEffectiveAnnotation(T)) {
|
||||
Diag.Report(Loc, NonHeapID) << T;
|
||||
Diag.Report(Loc, HeapNoteID);
|
||||
NonHeapClass.dumpAnnotationReason(Diag, T, Loc);
|
||||
}
|
||||
GlobalClass.reportErrorIfPresent(Diag, T, Loc, GlobalID, HeapNoteID);
|
||||
StackClass.reportErrorIfPresent(Diag, T, Loc, StackID, HeapNoteID);
|
||||
NonHeapClass.reportErrorIfPresent(Diag, T, Loc, NonHeapID, HeapNoteID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#define MOZ_HEAP_CLASS __attribute__((annotate("moz_heap_class")))
|
||||
#define MOZ_IMPLICIT __attribute__((annotate("moz_implicit")))
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
struct MOZ_HEAP_CLASS Heap {
|
||||
int i;
|
||||
Heap() {}
|
||||
MOZ_IMPLICIT Heap(int i) {}
|
||||
Heap(int i, int j) {}
|
||||
void *operator new(size_t x) throw() { return 0; }
|
||||
void *operator new(size_t blah, char *buffer) { return buffer; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct MOZ_HEAP_CLASS TemplateClass {
|
||||
T i;
|
||||
};
|
||||
|
||||
void gobble(void *) { }
|
||||
|
||||
void gobbleref(const Heap&) { }
|
||||
|
||||
void misuseHeapClass(int len) {
|
||||
Heap invalid; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}}
|
||||
Heap alsoInvalid[2]; // expected-error {{variable of type 'Heap [2]' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}} expected-note {{'Heap [2]' is a heap type because it is an array of heap type 'Heap'}}
|
||||
static Heap invalidStatic; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}}
|
||||
static Heap alsoInvalidStatic[2]; // expected-error {{variable of type 'Heap [2]' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}} expected-note {{'Heap [2]' is a heap type because it is an array of heap type 'Heap'}}
|
||||
|
||||
gobble(&invalid);
|
||||
gobble(&invalidStatic);
|
||||
gobble(&alsoInvalid[0]);
|
||||
|
||||
gobbleref(Heap()); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}}
|
||||
gobbleref(Heap(10, 20)); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}}
|
||||
gobbleref(Heap(10)); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}}
|
||||
gobbleref(10); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}}
|
||||
|
||||
gobble(new Heap);
|
||||
gobble(new Heap[10]);
|
||||
gobble(new TemplateClass<int>);
|
||||
gobble(len <= 5 ? &invalid : new Heap);
|
||||
|
||||
char buffer[sizeof(Heap)];
|
||||
gobble(new (buffer) Heap);
|
||||
}
|
||||
|
||||
Heap invalidStatic; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}}
|
||||
struct RandomClass {
|
||||
Heap nonstaticMember; // expected-note {{'RandomClass' is a heap type because member 'nonstaticMember' is a heap type 'Heap'}}
|
||||
static Heap staticMember; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}}
|
||||
};
|
||||
struct MOZ_HEAP_CLASS RandomHeapClass {
|
||||
Heap nonstaticMember;
|
||||
static Heap staticMember; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}}
|
||||
};
|
||||
|
||||
struct BadInherit : Heap {}; // expected-note {{'BadInherit' is a heap type because it inherits from a heap type 'Heap'}}
|
||||
struct MOZ_HEAP_CLASS GoodInherit : Heap {};
|
||||
|
||||
void useStuffWrongly() {
|
||||
BadInherit i; // expected-error {{variable of type 'BadInherit' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}}
|
||||
RandomClass r; // expected-error {{variable of type 'RandomClass' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ SOURCES += [
|
||||
'TestCustomHeap.cpp',
|
||||
'TestExplicitOperatorBool.cpp',
|
||||
'TestGlobalClass.cpp',
|
||||
'TestHeapClass.cpp',
|
||||
'TestInheritTypeAnnotationsFromTemplateArgs.cpp',
|
||||
'TestMultipleAnnotations.cpp',
|
||||
'TestMustOverride.cpp',
|
||||
|
||||
@@ -1502,10 +1502,6 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aB
|
||||
layerBuilder->SetLayerTreeCompressionMode();
|
||||
}
|
||||
|
||||
if (aFlags & PAINT_FLUSH_LAYERS) {
|
||||
FrameLayerBuilder::InvalidateAllLayers(layerManager);
|
||||
}
|
||||
|
||||
if (doBeginTransaction) {
|
||||
if (aCtx) {
|
||||
layerManager->BeginTransactionWithTarget(aCtx->ThebesContext());
|
||||
@@ -1702,10 +1698,6 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aB
|
||||
}
|
||||
}
|
||||
|
||||
if (aFlags & PAINT_FLUSH_LAYERS) {
|
||||
FrameLayerBuilder::InvalidateAllLayers(layerManager);
|
||||
}
|
||||
|
||||
layerManager->SetUserData(&gLayerManagerLayerBuilder, oldBuilder);
|
||||
return layerManager.forget();
|
||||
}
|
||||
@@ -2348,20 +2340,25 @@ nsDisplayBackgroundImage::IsSingleFixedPositionImage(nsDisplayListBuilder* aBuil
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackgroundImage::IsNonEmptyFixedImage() const
|
||||
{
|
||||
return mBackgroundStyle->mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
|
||||
!mBackgroundStyle->mLayers[mLayer].mImage.IsEmpty();
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackgroundImage::ShouldFixToViewport(LayerManager* aManager)
|
||||
{
|
||||
// APZ doesn't (yet) know how to scroll the visible region for these type of
|
||||
// items, so don't layerize them if it's enabled.
|
||||
if (nsLayoutUtils::UsesAsyncScrolling(mFrame) ||
|
||||
(aManager && aManager->ShouldAvoidComponentAlphaLayers())) {
|
||||
// APZ needs background-attachment:fixed images layerized for correctness.
|
||||
if (!nsLayoutUtils::UsesAsyncScrolling(mFrame) &&
|
||||
aManager && aManager->ShouldAvoidComponentAlphaLayers()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Put background-attachment:fixed background images in their own
|
||||
// compositing layer, unless we have APZ enabled
|
||||
return mBackgroundStyle->mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
|
||||
!mBackgroundStyle->mLayers[mLayer].mImage.IsEmpty();
|
||||
// compositing layer.
|
||||
return IsNonEmptyFixedImage();
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -2787,6 +2784,15 @@ nsDisplayBackgroundImage::GetBoundsInternal(nsDisplayListBuilder* aBuilder) {
|
||||
if (mFrame->GetType() == nsGkAtoms::canvasFrame) {
|
||||
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
|
||||
clipRect = frame->CanvasArea() + ToReferenceFrame();
|
||||
} else if (nsLayoutUtils::UsesAsyncScrolling(mFrame) && IsNonEmptyFixedImage()) {
|
||||
// If this is a background-attachment:fixed image, and APZ is enabled,
|
||||
// async scrolling could reveal additional areas of the image, so don't
|
||||
// clip it beyond clipping to the document's viewport.
|
||||
nsIFrame* rootFrame = presContext->PresShell()->GetRootFrame();
|
||||
nsRect rootRect = rootFrame->GetRectRelativeToSelf();
|
||||
if (nsLayoutUtils::TransformRect(rootFrame, mFrame, rootRect) == nsLayoutUtils::TRANSFORM_SUCCEEDED) {
|
||||
clipRect = rootRect + aBuilder->ToReferenceFrame(mFrame);
|
||||
}
|
||||
}
|
||||
const nsStyleBackground::Layer& layer = mBackgroundStyle->mLayers[mLayer];
|
||||
return nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame,
|
||||
@@ -5796,8 +5802,8 @@ nsCharClipDisplayItem::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool snap;
|
||||
nsRect newRect = geometry->mBounds;
|
||||
nsRect oldRect = GetBounds(aBuilder, &snap);
|
||||
if (mLeftEdge != geometry->mLeftEdge ||
|
||||
mRightEdge != geometry->mRightEdge ||
|
||||
if (mVisIStartEdge != geometry->mVisIStartEdge ||
|
||||
mVisIEndEdge != geometry->mVisIEndEdge ||
|
||||
!oldRect.IsEqualInterior(newRect) ||
|
||||
!geometry->mBorderRect.IsEqualInterior(GetBorderRect())) {
|
||||
aInvalidRegion->Or(oldRect, newRect);
|
||||
|
||||
+75
-60
@@ -166,8 +166,7 @@ public:
|
||||
/**
|
||||
* @param aReferenceFrame the frame at the root of the subtree; its origin
|
||||
* is the origin of the reference coordinate system for this display list
|
||||
* @param aIsForEvents true if we're creating this list in order to
|
||||
* determine which frame is under the mouse position
|
||||
* @param aMode encodes what the builder is being used for.
|
||||
* @param aBuildCaret whether or not we should include the caret in any
|
||||
* display lists that we make.
|
||||
*/
|
||||
@@ -1983,9 +1982,6 @@ public:
|
||||
* otherwise we will use a temporary BasicLayerManager and ctx must
|
||||
* not be null.
|
||||
*
|
||||
* If PAINT_FLUSH_LAYERS is set, we'll force a completely new layer
|
||||
* tree to be created for this paint *and* the next paint.
|
||||
*
|
||||
* If PAINT_EXISTING_TRANSACTION is set, the reference frame's widget's
|
||||
* layer manager has already had BeginTransaction() called on it and
|
||||
* we should not call it again.
|
||||
@@ -2002,7 +1998,6 @@ public:
|
||||
enum {
|
||||
PAINT_DEFAULT = 0,
|
||||
PAINT_USE_WIDGET_LAYERS = 0x01,
|
||||
PAINT_FLUSH_LAYERS = 0x02,
|
||||
PAINT_EXISTING_TRANSACTION = 0x04,
|
||||
PAINT_NO_COMPOSITE = 0x08,
|
||||
PAINT_COMPRESSED = 0x10
|
||||
@@ -2412,40 +2407,11 @@ protected:
|
||||
* is not yet a frame tree to go in the frame/iframe so we use the subdoc
|
||||
* frame of the parent document as a standin.
|
||||
*/
|
||||
class nsDisplaySolidColor : public nsDisplayItem {
|
||||
class nsDisplaySolidColorBase : public nsDisplayItem {
|
||||
public:
|
||||
nsDisplaySolidColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
const nsRect& aBounds, nscolor aColor)
|
||||
: nsDisplayItem(aBuilder, aFrame), mBounds(aBounds), mColor(aColor)
|
||||
{
|
||||
NS_ASSERTION(NS_GET_A(aColor) > 0, "Don't create invisible nsDisplaySolidColors!");
|
||||
MOZ_COUNT_CTOR(nsDisplaySolidColor);
|
||||
}
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
virtual ~nsDisplaySolidColor() {
|
||||
MOZ_COUNT_DTOR(nsDisplaySolidColor);
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
|
||||
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap) override {
|
||||
*aSnap = false;
|
||||
nsRegion result;
|
||||
if (NS_GET_A(mColor) == 255) {
|
||||
result = GetBounds(aBuilder, aSnap);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) override
|
||||
{
|
||||
*aColor = mColor;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) override;
|
||||
nsDisplaySolidColorBase(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nscolor aColor)
|
||||
: nsDisplayItem(aBuilder, aFrame), mColor(aColor)
|
||||
{}
|
||||
|
||||
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
|
||||
{
|
||||
@@ -2466,13 +2432,51 @@ public:
|
||||
ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
|
||||
}
|
||||
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap) override {
|
||||
*aSnap = false;
|
||||
nsRegion result;
|
||||
if (NS_GET_A(mColor) == 255) {
|
||||
result = GetBounds(aBuilder, aSnap);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) override
|
||||
{
|
||||
*aColor = mColor;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
nscolor mColor;
|
||||
};
|
||||
|
||||
class nsDisplaySolidColor : public nsDisplaySolidColorBase {
|
||||
public:
|
||||
nsDisplaySolidColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
const nsRect& aBounds, nscolor aColor)
|
||||
: nsDisplaySolidColorBase(aBuilder, aFrame, aColor), mBounds(aBounds)
|
||||
{
|
||||
NS_ASSERTION(NS_GET_A(aColor) > 0, "Don't create invisible nsDisplaySolidColors!");
|
||||
MOZ_COUNT_CTOR(nsDisplaySolidColor);
|
||||
}
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
virtual ~nsDisplaySolidColor() {
|
||||
MOZ_COUNT_DTOR(nsDisplaySolidColor);
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
|
||||
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) override;
|
||||
|
||||
virtual void WriteDebugInfo(std::stringstream& aStream) override;
|
||||
|
||||
NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR)
|
||||
|
||||
private:
|
||||
nsRect mBounds;
|
||||
nscolor mColor;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2566,6 +2570,7 @@ protected:
|
||||
bool IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aClipRect,
|
||||
gfxRect* aDestRect);
|
||||
bool IsNonEmptyFixedImage() const;
|
||||
nsRect GetBoundsInternal(nsDisplayListBuilder* aBuilder);
|
||||
|
||||
void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
|
||||
@@ -3884,11 +3889,12 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* This class adds basic support for limiting the rendering to the part inside
|
||||
* the specified edges. It's a base class for the display item classes that
|
||||
* does the actual work. The two members, mLeftEdge and mRightEdge, are
|
||||
* relative to the edges of the frame's scrollable overflow rectangle and is
|
||||
* the amount to suppress on each side.
|
||||
* This class adds basic support for limiting the rendering (in the inline axis
|
||||
* of the writing mode) to the part inside the specified edges. It's a base
|
||||
* class for the display item classes that do the actual work.
|
||||
* The two members, mVisIStartEdge and mVisIEndEdge, are relative to the edges
|
||||
* of the frame's scrollable overflow rectangle and are the amount to suppress
|
||||
* on each side.
|
||||
*
|
||||
* Setting none, both or only one edge is allowed.
|
||||
* The values must be non-negative.
|
||||
@@ -3897,7 +3903,7 @@ private:
|
||||
class nsCharClipDisplayItem : public nsDisplayItem {
|
||||
public:
|
||||
nsCharClipDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
|
||||
: nsDisplayItem(aBuilder, aFrame), mLeftEdge(0), mRightEdge(0) {}
|
||||
: nsDisplayItem(aBuilder, aFrame), mVisIStartEdge(0), mVisIEndEdge(0) {}
|
||||
|
||||
explicit nsCharClipDisplayItem(nsIFrame* aFrame)
|
||||
: nsDisplayItem(aFrame) {}
|
||||
@@ -3910,27 +3916,33 @@ public:
|
||||
|
||||
struct ClipEdges {
|
||||
ClipEdges(const nsDisplayItem& aItem,
|
||||
nscoord aLeftEdge, nscoord aRightEdge) {
|
||||
nscoord aVisIStartEdge, nscoord aVisIEndEdge) {
|
||||
nsRect r = aItem.Frame()->GetScrollableOverflowRect() +
|
||||
aItem.ToReferenceFrame();
|
||||
if (aItem.Frame()->GetWritingMode().IsVertical()) {
|
||||
mX = aLeftEdge > 0 ? r.y + aLeftEdge : nscoord_MIN;
|
||||
mXMost = aRightEdge > 0 ? std::max(r.YMost() - aRightEdge, mX) : nscoord_MAX;
|
||||
mVisIStart = aVisIStartEdge > 0 ? r.y + aVisIStartEdge : nscoord_MIN;
|
||||
mVisIEnd =
|
||||
aVisIEndEdge > 0 ? std::max(r.YMost() - aVisIEndEdge, mVisIStart)
|
||||
: nscoord_MAX;
|
||||
} else {
|
||||
mX = aLeftEdge > 0 ? r.x + aLeftEdge : nscoord_MIN;
|
||||
mXMost = aRightEdge > 0 ? std::max(r.XMost() - aRightEdge, mX) : nscoord_MAX;
|
||||
mVisIStart = aVisIStartEdge > 0 ? r.x + aVisIStartEdge : nscoord_MIN;
|
||||
mVisIEnd =
|
||||
aVisIEndEdge > 0 ? std::max(r.XMost() - aVisIEndEdge, mVisIStart)
|
||||
: nscoord_MAX;
|
||||
}
|
||||
}
|
||||
void Intersect(nscoord* aX, nscoord* aWidth) const {
|
||||
nscoord xmost1 = *aX + *aWidth;
|
||||
*aX = std::max(*aX, mX);
|
||||
*aWidth = std::max(std::min(xmost1, mXMost) - *aX, 0);
|
||||
void Intersect(nscoord* aVisIStart, nscoord* aVisISize) const {
|
||||
nscoord end = *aVisIStart + *aVisISize;
|
||||
*aVisIStart = std::max(*aVisIStart, mVisIStart);
|
||||
*aVisISize = std::max(std::min(end, mVisIEnd) - *aVisIStart, 0);
|
||||
}
|
||||
nscoord mX;
|
||||
nscoord mXMost;
|
||||
nscoord mVisIStart;
|
||||
nscoord mVisIEnd;
|
||||
};
|
||||
|
||||
ClipEdges Edges() const { return ClipEdges(*this, mLeftEdge, mRightEdge); }
|
||||
ClipEdges Edges() const {
|
||||
return ClipEdges(*this, mVisIStartEdge, mVisIEndEdge);
|
||||
}
|
||||
|
||||
static nsCharClipDisplayItem* CheckCast(nsDisplayItem* aItem) {
|
||||
nsDisplayItem::Type t = aItem->GetType();
|
||||
@@ -3940,8 +3952,11 @@ public:
|
||||
? static_cast<nsCharClipDisplayItem*>(aItem) : nullptr;
|
||||
}
|
||||
|
||||
nscoord mLeftEdge; // length from the left side
|
||||
nscoord mRightEdge; // length from the right side
|
||||
// Lengths measured from the visual inline start and end sides
|
||||
// (i.e. left and right respectively in horizontal writing modes,
|
||||
// regardless of bidi directionality; top and bottom in vertical modes).
|
||||
nscoord mVisIStartEdge;
|
||||
nscoord mVisIEndEdge;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -119,8 +119,8 @@ nsDisplaySVGEffectsGeometry::MoveBy(const nsPoint& aOffset)
|
||||
|
||||
nsCharClipGeometry::nsCharClipGeometry(nsCharClipDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
|
||||
: nsDisplayItemGenericGeometry(aItem, aBuilder)
|
||||
, mLeftEdge(aItem->mLeftEdge)
|
||||
, mRightEdge(aItem->mRightEdge)
|
||||
, mVisIStartEdge(aItem->mVisIStartEdge)
|
||||
, mVisIEndEdge(aItem->mVisIEndEdge)
|
||||
{}
|
||||
|
||||
nsDisplayTableItemGeometry::nsDisplayTableItemGeometry(nsDisplayTableItem* aItem,
|
||||
|
||||
@@ -255,8 +255,8 @@ class nsCharClipGeometry : public nsDisplayItemGenericGeometry
|
||||
public:
|
||||
nsCharClipGeometry(nsCharClipDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
|
||||
|
||||
nscoord mLeftEdge;
|
||||
nscoord mRightEdge;
|
||||
nscoord mVisIStartEdge;
|
||||
nscoord mVisIEndEdge;
|
||||
};
|
||||
|
||||
class nsDisplayTableItemGeometry
|
||||
|
||||
@@ -3061,6 +3061,18 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
TimeStamp startBuildDisplayList = TimeStamp::Now();
|
||||
nsDisplayListBuilder builder(aFrame, nsDisplayListBuilder::PAINTING,
|
||||
!(aFlags & PAINT_HIDE_CARET));
|
||||
if (aFlags & PAINT_IN_TRANSFORM) {
|
||||
builder.SetInTransform(true);
|
||||
}
|
||||
if (aFlags & PAINT_SYNC_DECODE_IMAGES) {
|
||||
builder.SetSyncDecodeImages(true);
|
||||
}
|
||||
if (aFlags & (PAINT_WIDGET_LAYERS | PAINT_TO_WINDOW)) {
|
||||
builder.SetPaintingToWindow(true);
|
||||
}
|
||||
if (aFlags & PAINT_IGNORE_SUPPRESSION) {
|
||||
builder.IgnorePaintSuppression();
|
||||
}
|
||||
|
||||
nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
|
||||
bool usingDisplayPort = false;
|
||||
@@ -3096,29 +3108,11 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
visibleRegion = aDirtyRegion;
|
||||
}
|
||||
|
||||
// If we're going to display something different from what we'd normally
|
||||
// paint in a window then we will flush out any retained layer trees before
|
||||
// *and after* we draw.
|
||||
bool willFlushRetainedLayers = (aFlags & PAINT_HIDE_CARET) != 0;
|
||||
|
||||
nsDisplayList list;
|
||||
if (aFlags & PAINT_IN_TRANSFORM) {
|
||||
builder.SetInTransform(true);
|
||||
}
|
||||
if (aFlags & PAINT_SYNC_DECODE_IMAGES) {
|
||||
builder.SetSyncDecodeImages(true);
|
||||
}
|
||||
if (aFlags & (PAINT_WIDGET_LAYERS | PAINT_TO_WINDOW)) {
|
||||
builder.SetPaintingToWindow(true);
|
||||
}
|
||||
if (aFlags & PAINT_IGNORE_SUPPRESSION) {
|
||||
builder.IgnorePaintSuppression();
|
||||
}
|
||||
|
||||
// If the root has embedded plugins, flag the builder so we know we'll need
|
||||
// to update plugin geometry after painting.
|
||||
if ((aFlags & PAINT_WIDGET_LAYERS) &&
|
||||
!willFlushRetainedLayers &&
|
||||
!(aFlags & PAINT_DOCUMENT_RELATIVE) &&
|
||||
rootPresContext->NeedToComputePluginGeometryUpdates()) {
|
||||
builder.SetWillComputePluginGeometry(true);
|
||||
@@ -3234,33 +3228,12 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
buildingDisplayList(&builder, aFrame, canvasArea, false);
|
||||
presShell->AddCanvasBackgroundColorItem(
|
||||
builder, list, aFrame, canvasArea, aBackstop);
|
||||
|
||||
// If the passed in backstop color makes us draw something different from
|
||||
// normal, we need to flush layers.
|
||||
if ((aFlags & PAINT_WIDGET_LAYERS) && !willFlushRetainedLayers) {
|
||||
nsView* view = aFrame->GetView();
|
||||
if (view) {
|
||||
nscolor backstop = presShell->ComputeBackstopColor(view);
|
||||
// The PresShell's canvas background color doesn't get updated until
|
||||
// EnterPresShell, so this check has to be done after that.
|
||||
nscolor canvasColor = presShell->GetCanvasBackground();
|
||||
if (NS_ComposeColors(aBackstop, canvasColor) !=
|
||||
NS_ComposeColors(backstop, canvasColor)) {
|
||||
willFlushRetainedLayers = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
builder.LeavePresShell(aFrame);
|
||||
Telemetry::AccumulateTimeDelta(Telemetry::PAINT_BUILD_DISPLAYLIST_TIME,
|
||||
startBuildDisplayList);
|
||||
|
||||
if (builder.GetHadToIgnorePaintSuppression()) {
|
||||
willFlushRetainedLayers = true;
|
||||
}
|
||||
|
||||
|
||||
bool profilerNeedsDisplayList = profiler_feature_active("displaylistdump");
|
||||
bool consoleNeedsDisplayList = gfxUtils::DumpDisplayList() || gfxUtils::sDumpPainting;
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
@@ -3304,16 +3277,7 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
uint32_t flags = nsDisplayList::PAINT_DEFAULT;
|
||||
if (aFlags & PAINT_WIDGET_LAYERS) {
|
||||
flags |= nsDisplayList::PAINT_USE_WIDGET_LAYERS;
|
||||
if (willFlushRetainedLayers) {
|
||||
// The caller wanted to paint from retained layers, but set up
|
||||
// the paint in such a way that we can't use them. We're going
|
||||
// to display something different from what we'd normally paint
|
||||
// in a window, so make sure we flush out any retained layer
|
||||
// trees before *and after* we draw. Callers should be fixed to
|
||||
// not do this.
|
||||
NS_WARNING("Flushing retained layers!");
|
||||
flags |= nsDisplayList::PAINT_FLUSH_LAYERS;
|
||||
} else if (!(aFlags & PAINT_DOCUMENT_RELATIVE)) {
|
||||
if (!(aFlags & PAINT_DOCUMENT_RELATIVE)) {
|
||||
nsIWidget *widget = aFrame->GetNearestWidget();
|
||||
if (widget) {
|
||||
// If we're finished building display list items for painting of the outermost
|
||||
@@ -3388,7 +3352,6 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
// glass boundaries on Windows. Also set up the window dragging region
|
||||
// and plugin clip regions and bounds.
|
||||
if ((aFlags & PAINT_WIDGET_LAYERS) &&
|
||||
!willFlushRetainedLayers &&
|
||||
!(aFlags & PAINT_DOCUMENT_RELATIVE)) {
|
||||
nsIWidget *widget = aFrame->GetNearestWidget();
|
||||
if (widget) {
|
||||
|
||||
@@ -690,14 +690,14 @@ TextOverflow::PruneDisplayListContents(nsDisplayList* aList,
|
||||
aInsideMarkersArea.IStart(mBlockWM) - rect.IStart(mBlockWM);
|
||||
if (istart > 0) {
|
||||
(mBlockWM.IsBidiLTR() ?
|
||||
charClip->mLeftEdge : charClip->mRightEdge) = istart;
|
||||
charClip->mVisIStartEdge : charClip->mVisIEndEdge) = istart;
|
||||
}
|
||||
}
|
||||
if (mIEnd.IsNeeded()) {
|
||||
nscoord iend = rect.IEnd(mBlockWM) - aInsideMarkersArea.IEnd(mBlockWM);
|
||||
if (iend > 0) {
|
||||
(mBlockWM.IsBidiLTR() ?
|
||||
charClip->mRightEdge : charClip->mLeftEdge) = iend;
|
||||
charClip->mVisIEndEdge : charClip->mVisIStartEdge) = iend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,8 +184,8 @@ class TextOverflow {
|
||||
|
||||
/**
|
||||
* Clip or remove items given the final marker edges. ("clip" here just means
|
||||
* assigning mLeftEdge/mRightEdge for any nsCharClipDisplayItem that needs it,
|
||||
* see nsDisplayList.h for a description of that item).
|
||||
* assigning mVisIStartEdge/mVisIEndEdge for any nsCharClipDisplayItem that
|
||||
* needs it; see nsDisplayList.h for a description of that item).
|
||||
* @param aFramesToHide remove display items for these frames
|
||||
* @param aInsideMarkersArea is the area inside the markers
|
||||
*/
|
||||
|
||||
@@ -195,11 +195,10 @@ protected:
|
||||
* We can also paint an "extra background color" behind the normal
|
||||
* background.
|
||||
*/
|
||||
class nsDisplayCanvasBackgroundColor : public nsDisplayItem {
|
||||
class nsDisplayCanvasBackgroundColor : public nsDisplaySolidColorBase {
|
||||
public:
|
||||
nsDisplayCanvasBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame)
|
||||
: nsDisplayItem(aBuilder, aFrame)
|
||||
, mColor(NS_RGBA(0,0,0,0))
|
||||
: nsDisplaySolidColorBase(aBuilder, aFrame, NS_RGBA(0,0,0,0))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -208,19 +207,6 @@ public:
|
||||
{
|
||||
return NS_GET_A(mColor) > 0;
|
||||
}
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap) override
|
||||
{
|
||||
if (NS_GET_A(mColor) == 255) {
|
||||
return nsRegion(GetBounds(aBuilder, aSnap));
|
||||
}
|
||||
return nsRegion();
|
||||
}
|
||||
virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) override
|
||||
{
|
||||
*aColor = mColor;
|
||||
return true;
|
||||
}
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override
|
||||
{
|
||||
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
|
||||
@@ -234,19 +220,6 @@ public:
|
||||
aOutFrames->AppendElement(mFrame);
|
||||
}
|
||||
|
||||
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
|
||||
{
|
||||
return new nsDisplayItemBoundsGeometry(this, aBuilder);
|
||||
}
|
||||
|
||||
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion) override
|
||||
{
|
||||
const nsDisplayItemBoundsGeometry* geometry = static_cast<const nsDisplayItemBoundsGeometry*>(aGeometry);
|
||||
ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
|
||||
}
|
||||
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx) override;
|
||||
|
||||
@@ -259,9 +232,6 @@ public:
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
virtual void WriteDebugInfo(std::stringstream& aStream) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
nscolor mColor;
|
||||
};
|
||||
|
||||
class nsDisplayCanvasBackgroundImage : public nsDisplayBackgroundImage {
|
||||
|
||||
@@ -4655,8 +4655,8 @@ public:
|
||||
nsRect newRect = geometry->mBounds;
|
||||
nsRect oldRect = GetBounds(aBuilder, &snap);
|
||||
if (decorations != geometry->mDecorations ||
|
||||
mLeftEdge != geometry->mLeftEdge ||
|
||||
mRightEdge != geometry->mRightEdge ||
|
||||
mVisIStartEdge != geometry->mVisIStartEdge ||
|
||||
mVisIEndEdge != geometry->mVisIEndEdge ||
|
||||
!oldRect.IsEqualInterior(newRect) ||
|
||||
!geometry->mBorderRect.IsEqualInterior(GetBorderRect())) {
|
||||
aInvalidRegion->Or(oldRect, newRect);
|
||||
@@ -4698,8 +4698,8 @@ nsDisplayText::Paint(nsDisplayListBuilder* aBuilder,
|
||||
ctx->Rectangle(pixelVisible);
|
||||
ctx->Clip();
|
||||
|
||||
NS_ASSERTION(mLeftEdge >= 0, "illegal left edge");
|
||||
NS_ASSERTION(mRightEdge >= 0, "illegal right edge");
|
||||
NS_ASSERTION(mVisIStartEdge >= 0, "illegal start edge");
|
||||
NS_ASSERTION(mVisIEndEdge >= 0, "illegal end edge");
|
||||
f->PaintText(aCtx, ToReferenceFrame(), extraVisible, *this);
|
||||
}
|
||||
|
||||
@@ -5772,13 +5772,13 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||
nsCSSShadowArray* shadow = textStyle->GetTextShadow();
|
||||
GetSelectionTextShadow(this, type, aTextPaintStyle, &shadow);
|
||||
if (shadow) {
|
||||
nscoord leftEdge = iOffset;
|
||||
nscoord startEdge = iOffset;
|
||||
if (mTextRun->IsRightToLeft()) {
|
||||
leftEdge -= mTextRun->GetAdvanceWidth(offset, length, &aProvider) +
|
||||
startEdge -= mTextRun->GetAdvanceWidth(offset, length, &aProvider) +
|
||||
hyphenWidth;
|
||||
}
|
||||
PaintShadows(shadow, offset, length, dirtyRect, aFramePt, textBaselinePt,
|
||||
leftEdge, aProvider, foreground, aClipEdges, aCtx);
|
||||
startEdge, aProvider, foreground, aClipEdges, aCtx);
|
||||
}
|
||||
|
||||
// Draw text segment
|
||||
@@ -6000,9 +6000,10 @@ ComputeTransformedLength(PropertyProvider& aProvider)
|
||||
}
|
||||
|
||||
bool
|
||||
nsTextFrame::MeasureCharClippedText(nscoord aLeftEdge, nscoord aRightEdge,
|
||||
nscoord* aSnappedLeftEdge,
|
||||
nscoord* aSnappedRightEdge)
|
||||
nsTextFrame::MeasureCharClippedText(nscoord aVisIStartEdge,
|
||||
nscoord aVisIEndEdge,
|
||||
nscoord* aSnappedStartEdge,
|
||||
nscoord* aSnappedEndEdge)
|
||||
{
|
||||
// We need a *reference* rendering context (not one that might have a
|
||||
// transform), so we don't have a rendering context argument.
|
||||
@@ -6017,9 +6018,9 @@ nsTextFrame::MeasureCharClippedText(nscoord aLeftEdge, nscoord aRightEdge,
|
||||
|
||||
uint32_t startOffset = provider.GetStart().GetSkippedOffset();
|
||||
uint32_t maxLength = ComputeTransformedLength(provider);
|
||||
return MeasureCharClippedText(provider, aLeftEdge, aRightEdge,
|
||||
return MeasureCharClippedText(provider, aVisIStartEdge, aVisIEndEdge,
|
||||
&startOffset, &maxLength,
|
||||
aSnappedLeftEdge, aSnappedRightEdge);
|
||||
aSnappedStartEdge, aSnappedEndEdge);
|
||||
}
|
||||
|
||||
static uint32_t GetClusterLength(gfxTextRun* aTextRun,
|
||||
@@ -6042,15 +6043,16 @@ static uint32_t GetClusterLength(gfxTextRun* aTextRun,
|
||||
|
||||
bool
|
||||
nsTextFrame::MeasureCharClippedText(PropertyProvider& aProvider,
|
||||
nscoord aLeftEdge, nscoord aRightEdge,
|
||||
nscoord aVisIStartEdge,
|
||||
nscoord aVisIEndEdge,
|
||||
uint32_t* aStartOffset,
|
||||
uint32_t* aMaxLength,
|
||||
nscoord* aSnappedLeftEdge,
|
||||
nscoord* aSnappedRightEdge)
|
||||
nscoord* aSnappedStartEdge,
|
||||
nscoord* aSnappedEndEdge)
|
||||
{
|
||||
*aSnappedLeftEdge = 0;
|
||||
*aSnappedRightEdge = 0;
|
||||
if (aLeftEdge <= 0 && aRightEdge <= 0) {
|
||||
*aSnappedStartEdge = 0;
|
||||
*aSnappedEndEdge = 0;
|
||||
if (aVisIStartEdge <= 0 && aVisIEndEdge <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6059,7 +6061,7 @@ nsTextFrame::MeasureCharClippedText(PropertyProvider& aProvider,
|
||||
const nscoord frameISize = ISize();
|
||||
const bool rtl = mTextRun->IsRightToLeft();
|
||||
gfxFloat advanceWidth = 0;
|
||||
const nscoord startEdge = rtl ? aRightEdge : aLeftEdge;
|
||||
const nscoord startEdge = rtl ? aVisIEndEdge : aVisIStartEdge;
|
||||
if (startEdge > 0) {
|
||||
const gfxFloat maxAdvance = gfxFloat(startEdge);
|
||||
while (maxLength > 0) {
|
||||
@@ -6073,12 +6075,12 @@ nsTextFrame::MeasureCharClippedText(PropertyProvider& aProvider,
|
||||
break;
|
||||
}
|
||||
}
|
||||
nscoord* snappedStartEdge = rtl ? aSnappedRightEdge : aSnappedLeftEdge;
|
||||
nscoord* snappedStartEdge = rtl ? aSnappedEndEdge : aSnappedStartEdge;
|
||||
*snappedStartEdge = NSToCoordFloor(advanceWidth);
|
||||
*aStartOffset = offset;
|
||||
}
|
||||
|
||||
const nscoord endEdge = rtl ? aLeftEdge : aRightEdge;
|
||||
const nscoord endEdge = rtl ? aVisIStartEdge : aVisIEndEdge;
|
||||
if (endEdge > 0) {
|
||||
const gfxFloat maxAdvance = gfxFloat(frameISize - endEdge);
|
||||
while (maxLength > 0) {
|
||||
@@ -6095,7 +6097,7 @@ nsTextFrame::MeasureCharClippedText(PropertyProvider& aProvider,
|
||||
offset += clusterLength;
|
||||
}
|
||||
maxLength = offset - *aStartOffset;
|
||||
nscoord* snappedEndEdge = rtl ? aSnappedLeftEdge : aSnappedRightEdge;
|
||||
nscoord* snappedEndEdge = rtl ? aSnappedStartEdge : aSnappedEndEdge;
|
||||
*snappedEndEdge = NSToCoordFloor(gfxFloat(frameISize) - advanceWidth);
|
||||
}
|
||||
*aMaxLength = maxLength;
|
||||
@@ -6206,18 +6208,18 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
|
||||
}
|
||||
uint32_t startOffset = provider.GetStart().GetSkippedOffset();
|
||||
uint32_t maxLength = ComputeTransformedLength(provider);
|
||||
nscoord snappedLeftEdge, snappedRightEdge;
|
||||
if (!MeasureCharClippedText(provider, aItem.mLeftEdge, aItem.mRightEdge,
|
||||
&startOffset, &maxLength, &snappedLeftEdge, &snappedRightEdge)) {
|
||||
nscoord snappedStartEdge, snappedEndEdge;
|
||||
if (!MeasureCharClippedText(provider, aItem.mVisIStartEdge, aItem.mVisIEndEdge,
|
||||
&startOffset, &maxLength, &snappedStartEdge, &snappedEndEdge)) {
|
||||
return;
|
||||
}
|
||||
if (verticalRun) {
|
||||
textBaselinePt.y += rtl ? -snappedRightEdge : snappedLeftEdge;
|
||||
textBaselinePt.y += rtl ? -snappedEndEdge : snappedStartEdge;
|
||||
} else {
|
||||
textBaselinePt.x += rtl ? -snappedRightEdge : snappedLeftEdge;
|
||||
textBaselinePt.x += rtl ? -snappedEndEdge : snappedStartEdge;
|
||||
}
|
||||
nsCharClipDisplayItem::ClipEdges clipEdges(aItem, snappedLeftEdge,
|
||||
snappedRightEdge);
|
||||
nsCharClipDisplayItem::ClipEdges clipEdges(aItem, snappedStartEdge,
|
||||
snappedEndEdge);
|
||||
nsTextPaintStyle textPaintStyle(this);
|
||||
textPaintStyle.SetResolveColors(!aCallbacks);
|
||||
|
||||
@@ -6241,7 +6243,7 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
|
||||
if (!aCallbacks) {
|
||||
const nsStyleText* textStyle = StyleText();
|
||||
PaintShadows(textStyle->mTextShadow, startOffset, maxLength,
|
||||
aDirtyRect, framePt, textBaselinePt, snappedLeftEdge, provider,
|
||||
aDirtyRect, framePt, textBaselinePt, snappedStartEdge, provider,
|
||||
foregroundColor, clipEdges, ctx);
|
||||
}
|
||||
|
||||
|
||||
@@ -303,15 +303,15 @@ public:
|
||||
|
||||
/**
|
||||
* Calculate the horizontal bounds of the grapheme clusters that fit entirely
|
||||
* inside the given left/right edges (which are positive lengths from the
|
||||
* respective frame edge). If an input value is zero it is ignored and the
|
||||
* result for that edge is zero. All out parameter values are undefined when
|
||||
* the method returns false.
|
||||
* inside the given left[top]/right[bottom] edges (which are positive lengths
|
||||
* from the respective frame edge). If an input value is zero it is ignored
|
||||
* and the result for that edge is zero. All out parameter values are
|
||||
* undefined when the method returns false.
|
||||
* @return true if at least one whole grapheme cluster fit between the edges
|
||||
*/
|
||||
bool MeasureCharClippedText(nscoord aLeftEdge, nscoord aRightEdge,
|
||||
nscoord* aSnappedLeftEdge,
|
||||
nscoord* aSnappedRightEdge);
|
||||
bool MeasureCharClippedText(nscoord aVisIStartEdge, nscoord aVisIEndEdge,
|
||||
nscoord* aSnappedStartEdge,
|
||||
nscoord* aSnappedEndEdge);
|
||||
/**
|
||||
* Same as above; this method also the returns the corresponding text run
|
||||
* offset and number of characters that fit. All out parameter values are
|
||||
@@ -319,10 +319,10 @@ public:
|
||||
* @return true if at least one whole grapheme cluster fit between the edges
|
||||
*/
|
||||
bool MeasureCharClippedText(PropertyProvider& aProvider,
|
||||
nscoord aLeftEdge, nscoord aRightEdge,
|
||||
nscoord aVisIStartEdge, nscoord aVisIEndEdge,
|
||||
uint32_t* aStartOffset, uint32_t* aMaxLength,
|
||||
nscoord* aSnappedLeftEdge,
|
||||
nscoord* aSnappedRightEdge);
|
||||
nscoord* aSnappedStartEdge,
|
||||
nscoord* aSnappedEndEdge);
|
||||
|
||||
/**
|
||||
* Object with various callbacks for PaintText() to invoke for different parts
|
||||
|
||||
+194
-87
@@ -340,13 +340,17 @@ GetBaselinePosition(nsTextFrame* aFrame,
|
||||
uint8_t aDominantBaseline,
|
||||
float aFontSizeScaleFactor)
|
||||
{
|
||||
// use a dummy WritingMode, because nsTextFrame::GetLogicalBaseLine
|
||||
// doesn't use it anyway
|
||||
WritingMode writingMode;
|
||||
WritingMode writingMode = aFrame->GetWritingMode();
|
||||
gfxTextRun::Metrics metrics =
|
||||
aTextRun->MeasureText(0, aTextRun->GetLength(), gfxFont::LOOSE_INK_EXTENTS,
|
||||
nullptr, nullptr);
|
||||
|
||||
switch (aDominantBaseline) {
|
||||
case NS_STYLE_DOMINANT_BASELINE_HANGING:
|
||||
case NS_STYLE_DOMINANT_BASELINE_TEXT_BEFORE_EDGE:
|
||||
return 0;
|
||||
return writingMode.IsVerticalRL()
|
||||
? metrics.mAscent + metrics.mDescent : 0;
|
||||
|
||||
case NS_STYLE_DOMINANT_BASELINE_USE_SCRIPT:
|
||||
case NS_STYLE_DOMINANT_BASELINE_NO_CHANGE:
|
||||
case NS_STYLE_DOMINANT_BASELINE_RESET_SIZE:
|
||||
@@ -354,23 +358,24 @@ GetBaselinePosition(nsTextFrame* aFrame,
|
||||
// support the complex baseline model that SVG 1.1 has and which
|
||||
// css3-linebox now defines.
|
||||
// (fall through)
|
||||
|
||||
case NS_STYLE_DOMINANT_BASELINE_AUTO:
|
||||
case NS_STYLE_DOMINANT_BASELINE_ALPHABETIC:
|
||||
return aFrame->GetLogicalBaseline(writingMode);
|
||||
return writingMode.IsVerticalRL()
|
||||
? metrics.mAscent + metrics.mDescent -
|
||||
aFrame->GetLogicalBaseline(writingMode)
|
||||
: aFrame->GetLogicalBaseline(writingMode);
|
||||
|
||||
case NS_STYLE_DOMINANT_BASELINE_MIDDLE:
|
||||
return aFrame->GetLogicalBaseline(writingMode) -
|
||||
SVGContentUtils::GetFontXHeight(aFrame) / 2.0 *
|
||||
aFrame->PresContext()->AppUnitsPerCSSPixel() * aFontSizeScaleFactor;
|
||||
}
|
||||
|
||||
gfxTextRun::Metrics metrics =
|
||||
aTextRun->MeasureText(0, aTextRun->GetLength(), gfxFont::LOOSE_INK_EXTENTS,
|
||||
nullptr, nullptr);
|
||||
|
||||
switch (aDominantBaseline) {
|
||||
case NS_STYLE_DOMINANT_BASELINE_TEXT_AFTER_EDGE:
|
||||
case NS_STYLE_DOMINANT_BASELINE_IDEOGRAPHIC:
|
||||
return metrics.mAscent + metrics.mDescent;
|
||||
return writingMode.IsVerticalLR()
|
||||
? 0 : metrics.mAscent + metrics.mDescent;
|
||||
|
||||
case NS_STYLE_DOMINANT_BASELINE_CENTRAL:
|
||||
case NS_STYLE_DOMINANT_BASELINE_MATHEMATICAL:
|
||||
return (metrics.mAscent + metrics.mDescent) / 2.0;
|
||||
@@ -526,6 +531,14 @@ struct TextRenderedRun
|
||||
return GetTextRun()->IsRightToLeft();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this rendered run is vertical.
|
||||
*/
|
||||
bool IsVertical() const
|
||||
{
|
||||
return GetTextRun()->IsVertical();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the transform that converts from a <text> element's user space into
|
||||
* the coordinate space that rendered runs can be painted directly in.
|
||||
@@ -720,7 +733,7 @@ struct TextRenderedRun
|
||||
* a selection mechanism for which glyphs will be painted, rather
|
||||
* than a geometric clip.
|
||||
*/
|
||||
void GetClipEdges(nscoord& aLeftEdge, nscoord& aRightEdge) const;
|
||||
void GetClipEdges(nscoord& aVisIStartEdge, nscoord& aVisIEndEdge) const;
|
||||
|
||||
/**
|
||||
* Returns the advance width of the whole rendered run.
|
||||
@@ -746,8 +759,12 @@ struct TextRenderedRun
|
||||
/**
|
||||
* The point in user space that the text is positioned at.
|
||||
*
|
||||
* For a horizontal run:
|
||||
* The x coordinate is the left edge of a LTR run of text or the right edge of
|
||||
* an RTL run. The y coordinate is the baseline of the text.
|
||||
* For a vertical run:
|
||||
* The x coordinate is the baseline of the text.
|
||||
* The y coordinate is the top edge of a LTR run, or bottom of RTL.
|
||||
*/
|
||||
gfxPoint mPosition;
|
||||
|
||||
@@ -770,7 +787,7 @@ struct TextRenderedRun
|
||||
|
||||
/**
|
||||
* The baseline in app units of this text run. The measurement is from the
|
||||
* top of the text frame.
|
||||
* top of the text frame. (From the left edge if vertical.)
|
||||
*/
|
||||
nscoord mBaseline;
|
||||
|
||||
@@ -816,10 +833,18 @@ TextRenderedRun::GetTransformFromUserSpaceForPainting(
|
||||
m.Scale(mLengthAdjustScaleFactor, 1.0);
|
||||
|
||||
// Translation to get the text frame in the right place.
|
||||
nsPoint t(IsRightToLeft() ?
|
||||
-mFrame->GetRect().width + aItem.mRightEdge :
|
||||
-aItem.mLeftEdge,
|
||||
-mBaseline);
|
||||
nsPoint t;
|
||||
if (IsVertical()) {
|
||||
t = nsPoint(-mBaseline,
|
||||
IsRightToLeft()
|
||||
? -mFrame->GetRect().height + aItem.mVisIEndEdge
|
||||
: -aItem.mVisIStartEdge);
|
||||
} else {
|
||||
t = nsPoint(IsRightToLeft()
|
||||
? -mFrame->GetRect().width + aItem.mVisIEndEdge
|
||||
: -aItem.mVisIStartEdge,
|
||||
-mBaseline);
|
||||
}
|
||||
m.Translate(AppUnitsToGfxUnits(t, aContext));
|
||||
|
||||
return m;
|
||||
@@ -837,8 +862,8 @@ TextRenderedRun::GetTransformFromRunUserSpaceToUserSpace(
|
||||
float cssPxPerDevPx = aContext->
|
||||
AppUnitsToFloatCSSPixels(aContext->AppUnitsPerDevPixel());
|
||||
|
||||
nscoord left, right;
|
||||
GetClipEdges(left, right);
|
||||
nscoord start, end;
|
||||
GetClipEdges(start, end);
|
||||
|
||||
// Glyph position in user space.
|
||||
m.Translate(mPosition);
|
||||
@@ -850,10 +875,18 @@ TextRenderedRun::GetTransformFromRunUserSpaceToUserSpace(
|
||||
m.Scale(mLengthAdjustScaleFactor, 1.0);
|
||||
|
||||
// Translation to get the text frame in the right place.
|
||||
nsPoint t(IsRightToLeft() ?
|
||||
-mFrame->GetRect().width + left + right :
|
||||
0,
|
||||
-mBaseline);
|
||||
nsPoint t;
|
||||
if (IsVertical()) {
|
||||
t = nsPoint(-mBaseline,
|
||||
IsRightToLeft()
|
||||
? -mFrame->GetRect().height + start + end
|
||||
: 0);
|
||||
} else {
|
||||
t = nsPoint(IsRightToLeft()
|
||||
? -mFrame->GetRect().width + start + end
|
||||
: 0,
|
||||
-mBaseline);
|
||||
}
|
||||
m.Translate(AppUnitsToGfxUnits(t, aContext) *
|
||||
cssPxPerDevPx / mFontSizeScaleFactor);
|
||||
|
||||
@@ -869,13 +902,15 @@ TextRenderedRun::GetTransformFromRunUserSpaceToFrameUserSpace(
|
||||
return m;
|
||||
}
|
||||
|
||||
nscoord left, right;
|
||||
GetClipEdges(left, right);
|
||||
nscoord start, end;
|
||||
GetClipEdges(start, end);
|
||||
|
||||
// Translate by the horizontal distance into the text frame this
|
||||
// rendered run is.
|
||||
return m.Translate(gfxPoint(gfxFloat(left) / aContext->AppUnitsPerCSSPixel(),
|
||||
0));
|
||||
gfxFloat appPerCssPx = aContext->AppUnitsPerCSSPixel();
|
||||
gfxPoint t = IsVertical() ? gfxPoint(0, start / appPerCssPx)
|
||||
: gfxPoint(start / appPerCssPx, 0);
|
||||
return m.Translate(t);
|
||||
}
|
||||
|
||||
SVGBBox
|
||||
@@ -895,8 +930,10 @@ TextRenderedRun::GetRunUserSpaceRect(nsPresContext* aContext,
|
||||
// horizontally.
|
||||
nsRect self = mFrame->GetVisualOverflowRectRelativeToSelf();
|
||||
nsRect rect = mFrame->GetRect();
|
||||
nscoord above = -self.y;
|
||||
nscoord below = self.YMost() - rect.height;
|
||||
bool vertical = IsVertical();
|
||||
nscoord above = vertical ? -self.x : -self.y;
|
||||
nscoord below = vertical ? self.XMost() - rect.width
|
||||
: self.YMost() - rect.height;
|
||||
|
||||
gfxSkipCharsIterator it = mFrame->EnsureTextRun(nsTextFrame::eInflated);
|
||||
gfxTextRun* textRun = mFrame->GetTextRun(nsTextFrame::eInflated);
|
||||
@@ -932,6 +969,11 @@ TextRenderedRun::GetRunUserSpaceRect(nsPresContext* aContext,
|
||||
}
|
||||
nsRect fillInAppUnits(x, baseline - above,
|
||||
width, metrics.mBoundingBox.height + above + below);
|
||||
if (textRun->IsVertical()) {
|
||||
// Swap line-relative textMetrics dimensions to physical coordinates.
|
||||
Swap(fillInAppUnits.x, fillInAppUnits.y);
|
||||
Swap(fillInAppUnits.width, fillInAppUnits.height);
|
||||
}
|
||||
|
||||
// Account for text-shadow.
|
||||
if (aFlags & eIncludeTextShadow) {
|
||||
@@ -949,7 +991,9 @@ TextRenderedRun::GetRunUserSpaceRect(nsPresContext* aContext,
|
||||
// Scale the rectangle up due to any mFontSizeScaleFactor. We scale
|
||||
// it around the text's origin.
|
||||
ScaleAround(fill,
|
||||
gfxPoint(0.0, aContext->AppUnitsToFloatCSSPixels(baseline)),
|
||||
textRun->IsVertical()
|
||||
? gfxPoint(aContext->AppUnitsToFloatCSSPixels(baseline), 0.0)
|
||||
: gfxPoint(0.0, aContext->AppUnitsToFloatCSSPixels(baseline)),
|
||||
1.0 / mFontSizeScaleFactor);
|
||||
|
||||
// Include the fill if requested.
|
||||
@@ -997,15 +1041,16 @@ TextRenderedRun::GetUserSpaceRect(nsPresContext* aContext,
|
||||
}
|
||||
|
||||
void
|
||||
TextRenderedRun::GetClipEdges(nscoord& aLeftEdge, nscoord& aRightEdge) const
|
||||
TextRenderedRun::GetClipEdges(nscoord& aVisIStartEdge,
|
||||
nscoord& aVisIEndEdge) const
|
||||
{
|
||||
uint32_t contentLength = mFrame->GetContentLength();
|
||||
if (mTextFrameContentOffset == 0 &&
|
||||
mTextFrameContentLength == contentLength) {
|
||||
// If the rendered run covers the entire content, we know we don't need
|
||||
// to clip without having to measure anything.
|
||||
aLeftEdge = 0;
|
||||
aRightEdge = 0;
|
||||
aVisIStartEdge = 0;
|
||||
aVisIEndEdge = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1035,22 +1080,22 @@ TextRenderedRun::GetClipEdges(nscoord& aLeftEdge, nscoord& aRightEdge) const
|
||||
|
||||
// Measure the advance width in the text run between the start of
|
||||
// frame's content and the start of the rendered run's content,
|
||||
nscoord leftEdge =
|
||||
nscoord startEdge =
|
||||
textRun->GetAdvanceWidth(frameOffset, runOffset - frameOffset, nullptr);
|
||||
|
||||
// and between the end of the rendered run's content and the end
|
||||
// of the frame's content.
|
||||
nscoord rightEdge =
|
||||
nscoord endEdge =
|
||||
textRun->GetAdvanceWidth(runOffset + runLength,
|
||||
frameOffset + frameLength - (runOffset + runLength),
|
||||
nullptr);
|
||||
|
||||
if (textRun->IsRightToLeft()) {
|
||||
aLeftEdge = rightEdge;
|
||||
aRightEdge = leftEdge;
|
||||
aVisIStartEdge = endEdge;
|
||||
aVisIEndEdge = startEdge;
|
||||
} else {
|
||||
aLeftEdge = leftEdge;
|
||||
aRightEdge = rightEdge;
|
||||
aVisIStartEdge = startEdge;
|
||||
aVisIEndEdge = endEdge;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1091,12 +1136,23 @@ TextRenderedRun::GetCharNumAtPosition(nsPresContext* aContext,
|
||||
gfxFloat ascent, descent;
|
||||
GetAscentAndDescentInAppUnits(mFrame, ascent, descent);
|
||||
|
||||
gfxFloat topEdge = mFrame->GetLogicalBaseline(mFrame->GetWritingMode()) - ascent;
|
||||
gfxFloat bottomEdge = topEdge + ascent + descent;
|
||||
|
||||
if (p.y < aContext->AppUnitsToGfxUnits(topEdge) ||
|
||||
p.y >= aContext->AppUnitsToGfxUnits(bottomEdge)) {
|
||||
return -1;
|
||||
WritingMode writingMode = mFrame->GetWritingMode();
|
||||
if (writingMode.IsVertical()) {
|
||||
gfxFloat leftEdge =
|
||||
mFrame->GetLogicalBaseline(writingMode) -
|
||||
(writingMode.IsVerticalRL() ? ascent : descent);
|
||||
gfxFloat rightEdge = leftEdge + ascent + descent;
|
||||
if (p.x < aContext->AppUnitsToGfxUnits(leftEdge) ||
|
||||
p.x > aContext->AppUnitsToGfxUnits(rightEdge)) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
gfxFloat topEdge = mFrame->GetLogicalBaseline(writingMode) - ascent;
|
||||
gfxFloat bottomEdge = topEdge + ascent + descent;
|
||||
if (p.y < aContext->AppUnitsToGfxUnits(topEdge) ||
|
||||
p.y > aContext->AppUnitsToGfxUnits(bottomEdge)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
gfxSkipCharsIterator it = mFrame->EnsureTextRun(nsTextFrame::eInflated);
|
||||
@@ -1111,7 +1167,8 @@ TextRenderedRun::GetCharNumAtPosition(nsPresContext* aContext,
|
||||
aContext->AppUnitsToGfxUnits(textRun->GetAdvanceWidth(offset, length,
|
||||
nullptr));
|
||||
|
||||
if (p.x < 0 || p.x >= runAdvance) {
|
||||
gfxFloat pos = writingMode.IsVertical() ? p.y : p.x;
|
||||
if (pos < 0 || pos >= runAdvance) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1124,8 +1181,8 @@ TextRenderedRun::GetCharNumAtPosition(nsPresContext* aContext,
|
||||
gfxFloat advance =
|
||||
aContext->AppUnitsToGfxUnits(textRun->GetAdvanceWidth(offset, length,
|
||||
nullptr));
|
||||
if ((rtl && p.x < runAdvance - advance) ||
|
||||
(!rtl && p.x >= advance)) {
|
||||
if ((rtl && pos < runAdvance - advance) ||
|
||||
(!rtl && pos >= advance)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -2684,7 +2741,7 @@ public:
|
||||
explicit SVGCharClipDisplayItem(const TextRenderedRun& aRun)
|
||||
: nsCharClipDisplayItem(aRun.mFrame)
|
||||
{
|
||||
aRun.GetClipEdges(mLeftEdge, mRightEdge);
|
||||
aRun.GetClipEdges(mVisIStartEdge, mVisIEndEdge);
|
||||
}
|
||||
|
||||
NS_DISPLAY_DECL_NAME("SVGText", TYPE_TEXT)
|
||||
@@ -4325,9 +4382,18 @@ SVGTextFrame::GetExtentOfChar(nsIContent* aContent,
|
||||
m.Rotate(mPositions[startIndex].mAngle);
|
||||
m.Scale(1 / mFontSizeScaleFactor, 1 / mFontSizeScaleFactor);
|
||||
|
||||
gfxRect glyphRect
|
||||
(x, -presContext->AppUnitsToGfxUnits(ascent) * cssPxPerDevPx,
|
||||
advance, presContext->AppUnitsToGfxUnits(ascent + descent) * cssPxPerDevPx);
|
||||
gfxRect glyphRect;
|
||||
if (it.TextRun()->IsVertical()) {
|
||||
glyphRect =
|
||||
gfxRect(-presContext->AppUnitsToGfxUnits(descent) * cssPxPerDevPx, x,
|
||||
presContext->AppUnitsToGfxUnits(ascent + descent) * cssPxPerDevPx,
|
||||
advance);
|
||||
} else {
|
||||
glyphRect =
|
||||
gfxRect(x, -presContext->AppUnitsToGfxUnits(ascent) * cssPxPerDevPx,
|
||||
advance,
|
||||
presContext->AppUnitsToGfxUnits(ascent + descent) * cssPxPerDevPx);
|
||||
}
|
||||
|
||||
// Transform the glyph's rect into user space.
|
||||
gfxRect r = m.TransformBounds(glyphRect);
|
||||
@@ -4631,11 +4697,21 @@ SVGTextFrame::DetermineCharPositions(nsTArray<nsPoint>& aPositions)
|
||||
|
||||
// Reset the position to the new frame's position.
|
||||
position = frit.Position();
|
||||
if (textRun->IsRightToLeft()) {
|
||||
position.x += frame->GetRect().width;
|
||||
if (textRun->IsVertical()) {
|
||||
if (textRun->IsRightToLeft()) {
|
||||
position.y += frame->GetRect().height;
|
||||
}
|
||||
position.x += GetBaselinePosition(frame, textRun,
|
||||
frit.DominantBaseline(),
|
||||
mFontSizeScaleFactor);
|
||||
} else {
|
||||
if (textRun->IsRightToLeft()) {
|
||||
position.x += frame->GetRect().width;
|
||||
}
|
||||
position.y += GetBaselinePosition(frame, textRun,
|
||||
frit.DominantBaseline(),
|
||||
mFontSizeScaleFactor);
|
||||
}
|
||||
position.y += GetBaselinePosition(frame, textRun, frit.DominantBaseline(),
|
||||
mFontSizeScaleFactor);
|
||||
|
||||
// Any characters not in a frame, e.g. when display:none.
|
||||
for (uint32_t i = 0; i < frit.UndisplayedCharacters(); i++) {
|
||||
@@ -4658,7 +4734,8 @@ SVGTextFrame::DetermineCharPositions(nsTArray<nsPoint>& aPositions)
|
||||
!textRun->IsClusterStart(it.GetSkippedOffset()))) {
|
||||
nscoord advance = textRun->GetAdvanceWidth(it.GetSkippedOffset(), 1,
|
||||
nullptr);
|
||||
position.x += textRun->IsRightToLeft() ? -advance : advance;
|
||||
(textRun->IsVertical() ? position.y : position.x) +=
|
||||
textRun->IsRightToLeft() ? -advance : advance;
|
||||
aPositions.AppendElement(lastPosition);
|
||||
it.AdvanceOriginal(1);
|
||||
}
|
||||
@@ -4673,7 +4750,8 @@ SVGTextFrame::DetermineCharPositions(nsTArray<nsPoint>& aPositions)
|
||||
uint32_t length = ClusterLength(textRun, it);
|
||||
nscoord advance = textRun->GetAdvanceWidth(it.GetSkippedOffset(),
|
||||
length, nullptr);
|
||||
position.x += textRun->IsRightToLeft() ? -advance : advance;
|
||||
(textRun->IsVertical() ? position.y : position.x) +=
|
||||
textRun->IsRightToLeft() ? -advance : advance;
|
||||
lastPosition = position;
|
||||
}
|
||||
it.AdvanceOriginal(1);
|
||||
@@ -4716,42 +4794,51 @@ ConvertLogicalTextAnchorToPhysical(uint8_t aTextAnchor, bool aIsRightToLeft)
|
||||
* character's initial position is the anchor point.
|
||||
* @param aChunkEnd The character index just after the end of the anchored
|
||||
* chunk.
|
||||
* @param aLeftEdge The left-most edge of any of the glyphs within the
|
||||
* anchored chunk.
|
||||
* @param aRightEdge The right-most edge of any of the glyphs within the
|
||||
* @param aVisIStartEdge The left/top-most edge of any of the glyphs within the
|
||||
* anchored chunk.
|
||||
* @param aVisIEndEdge The right/bottom-most edge of any of the glyphs within
|
||||
* the anchored chunk.
|
||||
* @param aAnchorSide The direction to anchor.
|
||||
*/
|
||||
static void
|
||||
ShiftAnchoredChunk(nsTArray<mozilla::CharPosition>& aCharPositions,
|
||||
uint32_t aChunkStart,
|
||||
uint32_t aChunkEnd,
|
||||
gfxFloat aLeftEdge,
|
||||
gfxFloat aRightEdge,
|
||||
TextAnchorSide aAnchorSide)
|
||||
gfxFloat aVisIStartEdge,
|
||||
gfxFloat aVisIEndEdge,
|
||||
TextAnchorSide aAnchorSide,
|
||||
bool aVertical)
|
||||
{
|
||||
NS_ASSERTION(aLeftEdge <= aRightEdge, "unexpected anchored chunk edges");
|
||||
NS_ASSERTION(aChunkStart < aChunkEnd, "unexpected values for aChunkStart and "
|
||||
"aChunkEnd");
|
||||
NS_ASSERTION(aVisIStartEdge <= aVisIEndEdge,
|
||||
"unexpected anchored chunk edges");
|
||||
NS_ASSERTION(aChunkStart < aChunkEnd,
|
||||
"unexpected values for aChunkStart and aChunkEnd");
|
||||
|
||||
gfxFloat shift = aCharPositions[aChunkStart].mPosition.x;
|
||||
gfxFloat shift = aVertical ? aCharPositions[aChunkStart].mPosition.y
|
||||
: aCharPositions[aChunkStart].mPosition.x;
|
||||
switch (aAnchorSide) {
|
||||
case eAnchorLeft:
|
||||
shift -= aLeftEdge;
|
||||
shift -= aVisIStartEdge;
|
||||
break;
|
||||
case eAnchorMiddle:
|
||||
shift -= (aLeftEdge + aRightEdge) / 2;
|
||||
shift -= (aVisIStartEdge + aVisIEndEdge) / 2;
|
||||
break;
|
||||
case eAnchorRight:
|
||||
shift -= aRightEdge;
|
||||
shift -= aVisIEndEdge;
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("unexpected value for aAnchorSide");
|
||||
}
|
||||
|
||||
if (shift != 0.0) {
|
||||
for (uint32_t i = aChunkStart; i < aChunkEnd; i++) {
|
||||
aCharPositions[i].mPosition.x += shift;
|
||||
if (aVertical) {
|
||||
for (uint32_t i = aChunkStart; i < aChunkEnd; i++) {
|
||||
aCharPositions[i].mPosition.y += shift;
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = aChunkStart; i < aChunkEnd; i++) {
|
||||
aCharPositions[i].mPosition.x += shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4803,6 +4890,9 @@ SVGTextFrame::AdjustPositionsForClusters()
|
||||
it.GetGlyphPartialAdvance(partLength, presContext) / mFontSizeScaleFactor;
|
||||
gfxPoint direction = gfxPoint(cos(angle), sin(angle)) *
|
||||
(it.TextRun()->IsRightToLeft() ? -1.0 : 1.0);
|
||||
if (it.TextRun()->IsVertical()) {
|
||||
Swap(direction.x, direction.y);
|
||||
}
|
||||
mPositions[charIndex].mPosition = mPositions[startIndex].mPosition +
|
||||
direction * advance;
|
||||
|
||||
@@ -4945,7 +5035,10 @@ SVGTextFrame::DoTextPathLayout()
|
||||
gfxFloat halfAdvance =
|
||||
it.GetGlyphAdvance(context) / mFontSizeScaleFactor / 2.0;
|
||||
gfxFloat sign = it.TextRun()->IsRightToLeft() ? -1.0 : 1.0;
|
||||
gfxFloat midx = mPositions[i].mPosition.x + sign * halfAdvance + offset;
|
||||
bool vertical = it.TextRun()->IsVertical();
|
||||
gfxFloat midx = (vertical ? mPositions[i].mPosition.y
|
||||
: mPositions[i].mPosition.x) +
|
||||
sign * halfAdvance + offset;
|
||||
|
||||
// Hide the character if it falls off the end of the path.
|
||||
mPositions[i].mHidden = midx < 0 || midx > pathLength;
|
||||
@@ -4953,9 +5046,11 @@ SVGTextFrame::DoTextPathLayout()
|
||||
// Position the character on the path at the right angle.
|
||||
Point tangent; // Unit vector tangent to the point we find.
|
||||
Point pt = path->ComputePointAtLength(Float(midx), &tangent);
|
||||
Float rotation = atan2f(tangent.y, tangent.x);
|
||||
Float rotation = vertical ? atan2f(-tangent.x, tangent.y)
|
||||
: atan2f(tangent.y, tangent.x);
|
||||
Point normal(-tangent.y, tangent.x); // Unit vector normal to the point.
|
||||
Point offsetFromPath = normal * mPositions[i].mPosition.y;
|
||||
Point offsetFromPath = normal * (vertical ? mPositions[i].mPosition.x
|
||||
: mPositions[i].mPosition.y);
|
||||
pt += offsetFromPath;
|
||||
Point direction = tangent * sign;
|
||||
mPositions[i].mPosition = ThebesPoint(pt) - ThebesPoint(direction) * halfAdvance;
|
||||
@@ -4991,6 +5086,7 @@ SVGTextFrame::DoAnchoring()
|
||||
it.Next();
|
||||
}
|
||||
|
||||
bool vertical = GetWritingMode().IsVertical();
|
||||
uint32_t start = it.TextElementCharIndex();
|
||||
while (start < mPositions.Length()) {
|
||||
it.AdvanceToCharacter(start);
|
||||
@@ -5005,12 +5101,15 @@ SVGTextFrame::DoAnchoring()
|
||||
do {
|
||||
if (!it.IsOriginalCharSkipped() && !it.IsOriginalCharTrimmed()) {
|
||||
gfxFloat advance = it.GetAdvance(presContext) / mFontSizeScaleFactor;
|
||||
gfxFloat pos =
|
||||
it.TextRun()->IsVertical() ? mPositions[index].mPosition.y
|
||||
: mPositions[index].mPosition.x;
|
||||
if (it.TextRun()->IsRightToLeft()) {
|
||||
left = std::min(left, mPositions[index].mPosition.x - advance);
|
||||
right = std::max(right, mPositions[index].mPosition.x);
|
||||
left = std::min(left, pos - advance);
|
||||
right = std::max(right, pos);
|
||||
} else {
|
||||
left = std::min(left, mPositions[index].mPosition.x);
|
||||
right = std::max(right, mPositions[index].mPosition.x + advance);
|
||||
left = std::min(left, pos);
|
||||
right = std::max(right, pos + advance);
|
||||
}
|
||||
}
|
||||
it.Next();
|
||||
@@ -5024,7 +5123,8 @@ SVGTextFrame::DoAnchoring()
|
||||
ConvertLogicalTextAnchorToPhysical(chunkFrame->StyleSVG()->mTextAnchor,
|
||||
isRTL);
|
||||
|
||||
ShiftAnchoredChunk(mPositions, start, end, left, right, anchor);
|
||||
ShiftAnchoredChunk(mPositions, start, end, left, right, anchor,
|
||||
vertical);
|
||||
}
|
||||
|
||||
start = it.TextElementCharIndex();
|
||||
@@ -5095,6 +5195,7 @@ SVGTextFrame::DoGlyphPositioning()
|
||||
}
|
||||
|
||||
nsPresContext* presContext = PresContext();
|
||||
bool vertical = GetWritingMode().IsVertical();
|
||||
|
||||
float cssPxPerDevPx = presContext->
|
||||
AppUnitsToFloatCSSPixels(presContext->AppUnitsPerDevPixel());
|
||||
@@ -5105,9 +5206,10 @@ SVGTextFrame::DoGlyphPositioning()
|
||||
double adjustment = 0.0;
|
||||
mLengthAdjustScaleFactor = 1.0f;
|
||||
if (adjustingTextLength) {
|
||||
nscoord frameWidth = GetFirstPrincipalChild()->GetRect().width;
|
||||
nscoord frameLength = vertical ? GetFirstPrincipalChild()->GetRect().height
|
||||
: GetFirstPrincipalChild()->GetRect().width;
|
||||
float actualTextLength =
|
||||
static_cast<float>(presContext->AppUnitsToGfxUnits(frameWidth) * factor);
|
||||
static_cast<float>(presContext->AppUnitsToGfxUnits(frameLength) * factor);
|
||||
|
||||
nsRefPtr<SVGAnimatedEnumeration> lengthAdjustEnum = element->LengthAdjust();
|
||||
uint16_t lengthAdjust = lengthAdjustEnum->AnimVal();
|
||||
@@ -5141,14 +5243,16 @@ SVGTextFrame::DoGlyphPositioning()
|
||||
mPositions[0].mPosition += deltas[0];
|
||||
}
|
||||
|
||||
gfxFloat xLengthAdjustFactor = vertical ? 1.0 : mLengthAdjustScaleFactor;
|
||||
gfxFloat yLengthAdjustFactor = vertical ? mLengthAdjustScaleFactor : 1.0;
|
||||
for (uint32_t i = 1; i < mPositions.Length(); i++) {
|
||||
// Fill in unspecified x position.
|
||||
if (!mPositions[i].IsXSpecified()) {
|
||||
nscoord d = charPositions[i].x - charPositions[i - 1].x;
|
||||
mPositions[i].mPosition.x =
|
||||
mPositions[i - 1].mPosition.x +
|
||||
presContext->AppUnitsToGfxUnits(d) * factor * mLengthAdjustScaleFactor;
|
||||
if (!mPositions[i].mUnaddressable) {
|
||||
presContext->AppUnitsToGfxUnits(d) * factor * xLengthAdjustFactor;
|
||||
if (!vertical && !mPositions[i].mUnaddressable) {
|
||||
mPositions[i].mPosition.x += adjustment;
|
||||
}
|
||||
}
|
||||
@@ -5157,7 +5261,10 @@ SVGTextFrame::DoGlyphPositioning()
|
||||
nscoord d = charPositions[i].y - charPositions[i - 1].y;
|
||||
mPositions[i].mPosition.y =
|
||||
mPositions[i - 1].mPosition.y +
|
||||
presContext->AppUnitsToGfxUnits(d) * factor;
|
||||
presContext->AppUnitsToGfxUnits(d) * factor * yLengthAdjustFactor;
|
||||
if (vertical && !mPositions[i].mUnaddressable) {
|
||||
mPositions[i].mPosition.y += adjustment;
|
||||
}
|
||||
}
|
||||
// Add in dx/dy.
|
||||
if (i < deltas.Length()) {
|
||||
|
||||
Reference in New Issue
Block a user