mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-06-05 07:59:28 +00:00
Implement getAlignmentBaseline and getBaselineShift in ios. (#527)
* Implement correct transform parser * Implement getAlignmentBaseline and getBaselineShift in ios. Add comments to glyphcontext and align with android. Implement correct isWordSeparator predicate. Cleanup GlyphContext j2objc remnants. * Fix getBaselineShift bugs and font data invalidation.
This commit is contained in:
committed by
Dustin Savery
parent
4821a7cd3a
commit
ec2a967592
@@ -34,8 +34,7 @@
|
||||
|
||||
- (void)popContext;
|
||||
|
||||
- (void)pushContextwithRNSVGText:(RNSVGText *)node
|
||||
reset:(bool)reset
|
||||
- (void)pushContext:(RNSVGText *)node
|
||||
font:(NSDictionary *)font
|
||||
x:(NSArray*)x
|
||||
y:(NSArray*)y
|
||||
@@ -43,7 +42,7 @@
|
||||
deltaY:(NSArray*)deltaY
|
||||
rotate:(NSArray*)rotate;
|
||||
|
||||
- (void)pushContextWithRNSVGGroup:(RNSVGGroup*)node
|
||||
- (void)pushContext:(RNSVGGroup*)node
|
||||
font:(NSDictionary *)font;
|
||||
|
||||
|
||||
|
||||
+209
-170
@@ -5,74 +5,105 @@
|
||||
#import "FontData.h"
|
||||
#import "RNSVGText.h"
|
||||
|
||||
// https://www.w3.org/TR/SVG/text.html#TSpanElement
|
||||
@interface GlyphContext () {
|
||||
@public
|
||||
// Current stack (one per node push/pop)
|
||||
NSMutableArray *mFontContext_;
|
||||
|
||||
// Unique input attribute lists (only added if node sets a value)
|
||||
NSMutableArray *mXsContext_;
|
||||
NSMutableArray *mYsContext_;
|
||||
NSMutableArray *mDXsContext_;
|
||||
NSMutableArray *mDYsContext_;
|
||||
NSMutableArray *mRsContext_;
|
||||
|
||||
// Unique index into attribute list (one per unique list)
|
||||
NSMutableArray *mXIndices_;
|
||||
NSMutableArray *mYIndices_;
|
||||
NSMutableArray *mDXIndices_;
|
||||
NSMutableArray *mDYIndices_;
|
||||
NSMutableArray *mRIndices_;
|
||||
|
||||
// Index of unique context used (one per node push/pop)
|
||||
NSMutableArray *mXsIndices_;
|
||||
NSMutableArray *mYsIndices_;
|
||||
NSMutableArray *mDXsIndices_;
|
||||
NSMutableArray *mDYsIndices_;
|
||||
NSMutableArray *mRsIndices_;
|
||||
|
||||
// Calculated on push context, percentage and em length depends on parent font size
|
||||
double mFontSize_;
|
||||
FontData *topFont_;
|
||||
|
||||
// Current accumulated values
|
||||
// https://www.w3.org/TR/SVG/types.html#DataTypeCoordinate
|
||||
// <coordinate> syntax is the same as that for <length>
|
||||
double mX_;
|
||||
double mY_;
|
||||
|
||||
// https://www.w3.org/TR/SVG/types.html#Length
|
||||
double mDX_;
|
||||
double mDY_;
|
||||
|
||||
// Current <list-of-coordinates> SVGLengthList
|
||||
// https://www.w3.org/TR/SVG/types.html#InterfaceSVGLengthList
|
||||
// https://www.w3.org/TR/SVG/types.html#DataTypeCoordinates
|
||||
|
||||
// https://www.w3.org/TR/SVG/text.html#TSpanElementXAttribute
|
||||
NSArray *mXs_;
|
||||
|
||||
// https://www.w3.org/TR/SVG/text.html#TSpanElementYAttribute
|
||||
NSArray *mYs_;
|
||||
|
||||
// Current <list-of-lengths> SVGLengthList
|
||||
// https://www.w3.org/TR/SVG/types.html#DataTypeLengths
|
||||
|
||||
// https://www.w3.org/TR/SVG/text.html#TSpanElementDXAttribute
|
||||
NSArray *mDXs_;
|
||||
|
||||
// https://www.w3.org/TR/SVG/text.html#TSpanElementDYAttribute
|
||||
NSArray *mDYs_;
|
||||
|
||||
// Current <list-of-numbers> SVGLengthList
|
||||
// https://www.w3.org/TR/SVG/types.html#DataTypeNumbers
|
||||
|
||||
// https://www.w3.org/TR/SVG/text.html#TSpanElementRotateAttribute
|
||||
NSArray *mRs_;
|
||||
|
||||
// Current attribute list index
|
||||
long mXsIndex_;
|
||||
long mYsIndex_;
|
||||
long mDXsIndex_;
|
||||
long mDYsIndex_;
|
||||
long mRsIndex_;
|
||||
|
||||
// Current value index in current attribute list
|
||||
long mXIndex_;
|
||||
long mYIndex_;
|
||||
long mDXIndex_;
|
||||
long mDYIndex_;
|
||||
long mRIndex_;
|
||||
|
||||
// Top index of stack
|
||||
long mTop_;
|
||||
|
||||
// Constructor parameters
|
||||
float mScale_;
|
||||
float mWidth_;
|
||||
float mHeight_;
|
||||
}
|
||||
|
||||
- (void)pushIndices;
|
||||
- (void)pushContext:(RNSVGText *)node
|
||||
font:(NSDictionary *)font
|
||||
x:(NSArray*)x
|
||||
y:(NSArray*)y
|
||||
deltaX:(NSArray*)deltaX
|
||||
deltaY:(NSArray*)deltaY
|
||||
rotate:(NSArray*)rotate;
|
||||
|
||||
- (void)reset;
|
||||
|
||||
- (FontData *)getTopOrParentFontWithRNSVGGroup:(RNSVGGroup *)child;
|
||||
|
||||
- (void)pushNodeAndFontWithRNSVGGroup:(RNSVGGroup *)node
|
||||
withNSDictionary:(NSDictionary *)font;
|
||||
|
||||
+ (void)incrementIndicesWithNSArray:(NSArray *)indices
|
||||
withLong:(long)topIndex;
|
||||
|
||||
- (void)pushContextwithRNSVGText:(RNSVGText *)node
|
||||
reset:(bool)reset
|
||||
font:(NSDictionary *)font
|
||||
x:(NSArray*)x
|
||||
y:(NSArray*)y
|
||||
deltaX:(NSArray*)deltaX
|
||||
deltaY:(NSArray*)deltaY
|
||||
rotate:(NSArray*)rotate;
|
||||
|
||||
- (void)pushContextWithRNSVGGroup:(RNSVGGroup*)node
|
||||
font:(NSDictionary *)font;
|
||||
- (void)pushContext:(RNSVGGroup*)node
|
||||
font:(NSDictionary *)font;
|
||||
@end
|
||||
|
||||
@implementation GlyphContext
|
||||
@@ -82,7 +113,7 @@
|
||||
{
|
||||
NSString *fontFamily = topFont_->fontFamily;
|
||||
NSNumber * fontSize = [NSNumber numberWithDouble:topFont_->fontSize];
|
||||
|
||||
|
||||
NSString * fontWeight = [FontWeightToString(topFont_->fontWeight) lowercaseString];
|
||||
NSString * fontStyle = FontStyleStrings[topFont_->fontStyle];
|
||||
|
||||
@@ -110,52 +141,122 @@
|
||||
scaleMultiplier:1.0];
|
||||
}
|
||||
|
||||
- (void)pushIndices {
|
||||
GlyphContext_pushIndices(self);
|
||||
void pushIndices(GlyphContext *self) {
|
||||
[self->mXsIndices_ addObject:[NSNumber numberWithLong:self->mXsIndex_]];
|
||||
[self->mYsIndices_ addObject:[NSNumber numberWithLong:self->mYsIndex_]];
|
||||
[self->mDXsIndices_ addObject:[NSNumber numberWithLong:self->mDXsIndex_]];
|
||||
[self->mDYsIndices_ addObject:[NSNumber numberWithLong:self->mDYsIndex_]];
|
||||
[self->mRsIndices_ addObject:[NSNumber numberWithLong:self->mRsIndex_]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithScale:(float)scale_
|
||||
width:(float)width
|
||||
height:(float)height {
|
||||
GlyphContext_initWithFloat_withFloat_withFloat_(self, scale_, width, height);
|
||||
return self;
|
||||
}
|
||||
self->mFontContext_ = [[NSMutableArray alloc]init];
|
||||
self->mXsContext_ = [[NSMutableArray alloc]init];
|
||||
self->mYsContext_ = [[NSMutableArray alloc]init];
|
||||
self->mDXsContext_ = [[NSMutableArray alloc]init];
|
||||
self->mDYsContext_ = [[NSMutableArray alloc]init];
|
||||
self->mRsContext_ = [[NSMutableArray alloc]init];
|
||||
|
||||
- (void)reset {
|
||||
GlyphContext_reset(self);
|
||||
self->mXIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mYIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mDXIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mDYIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mRIndices_ = [[NSMutableArray alloc]init];
|
||||
|
||||
self->mXsIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mYsIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mDXsIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mDYsIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mRsIndices_ = [[NSMutableArray alloc]init];
|
||||
|
||||
self->mFontSize_ = FontData_DEFAULT_FONT_SIZE;
|
||||
self->topFont_ = [FontData Defaults];
|
||||
|
||||
self->mXs_ = [[NSArray alloc]init];
|
||||
self->mYs_ = [[NSArray alloc]init];
|
||||
self->mDXs_ = [[NSArray alloc]init];
|
||||
self->mDYs_ = [[NSArray alloc]init];
|
||||
self->mRs_ = [[NSArray alloc]initWithObjects:@0, nil];
|
||||
|
||||
self->mXIndex_ = -1;
|
||||
self->mYIndex_ = -1;
|
||||
self->mDXIndex_ = -1;
|
||||
self->mDYIndex_ = -1;
|
||||
self->mRIndex_ = -1;
|
||||
|
||||
self->mScale_ = scale_;
|
||||
self->mWidth_ = width;
|
||||
self->mHeight_ = height;
|
||||
|
||||
[self->mXsContext_ addObject:self->mXs_];
|
||||
[self->mYsContext_ addObject:self->mYs_];
|
||||
[self->mDXsContext_ addObject:self->mDXs_];
|
||||
[self->mDYsContext_ addObject:self->mDYs_];
|
||||
[self->mRsContext_ addObject:self->mRs_];
|
||||
|
||||
[self->mXIndices_ addObject:[NSNumber numberWithLong:self->mXIndex_]];
|
||||
[self->mYIndices_ addObject:[NSNumber numberWithLong:self->mYIndex_]];
|
||||
[self->mDXIndices_ addObject:[NSNumber numberWithLong:self->mDXIndex_]];
|
||||
[self->mDYIndices_ addObject:[NSNumber numberWithLong:self->mDYIndex_]];
|
||||
[self->mRIndices_ addObject:[NSNumber numberWithLong:self->mRIndex_]];
|
||||
|
||||
[self->mFontContext_ addObject:self->topFont_];
|
||||
pushIndices(self);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (FontData *)getFont {
|
||||
return topFont_;
|
||||
}
|
||||
|
||||
- (FontData *)getTopOrParentFontWithRNSVGGroup:(RNSVGGroup*)child {
|
||||
return GlyphContext_getTopOrParentFontWithRNSVGGroup_(self, child);
|
||||
}
|
||||
|
||||
- (void)pushNodeAndFontWithRNSVGGroup:(RNSVGGroup*)node
|
||||
withNSDictionary:(NSDictionary*)font {
|
||||
GlyphContext_pushNodeAndFontWithRNSVGGroup_withNSDictionary_(self, node, font);
|
||||
}
|
||||
|
||||
- (void)pushContextWithRNSVGGroup:(RNSVGGroup*)node
|
||||
font:(NSDictionary*)font {
|
||||
GlyphContext_pushNodeAndFontWithRNSVGGroup_withNSDictionary_(self, node, font);
|
||||
GlyphContext_pushIndices(self);
|
||||
}
|
||||
|
||||
- (void)pushContextwithRNSVGText:(RNSVGText*)node
|
||||
reset:(bool)reset
|
||||
font:(NSDictionary*)font
|
||||
x:(NSArray*)x
|
||||
y:(NSArray*)y
|
||||
deltaX:(NSArray*)deltaX
|
||||
deltaY:(NSArray*)deltaY
|
||||
rotate:(NSArray*)rotate {
|
||||
if (reset) {
|
||||
GlyphContext_reset(self);
|
||||
FontData *getTopOrParentFont(GlyphContext *self, RNSVGGroup* child) {
|
||||
if (self->mTop_ > 0) {
|
||||
return self->topFont_;
|
||||
} else {
|
||||
RNSVGGroup* parentRoot = [child getParentTextRoot];
|
||||
FontData* Defaults = [FontData Defaults];
|
||||
while (parentRoot != nil) {
|
||||
FontData *map = [[parentRoot getGlyphContext] getFont];
|
||||
if (map != Defaults) {
|
||||
return map;
|
||||
}
|
||||
parentRoot = [parentRoot getParentTextRoot];
|
||||
}
|
||||
return Defaults;
|
||||
}
|
||||
GlyphContext_pushNodeAndFontWithRNSVGGroup_withNSDictionary_(self, (RNSVGGroup*)node, font);
|
||||
}
|
||||
|
||||
void pushNodeAndFont(GlyphContext *self, RNSVGGroup* node, NSDictionary* font) {
|
||||
FontData *parent = getTopOrParentFont(self, node);
|
||||
self->mTop_++;
|
||||
if (font == nil) {
|
||||
[self->mFontContext_ addObject:parent];
|
||||
return;
|
||||
}
|
||||
FontData *data = [FontData initWithNSDictionary:font
|
||||
parent:parent
|
||||
scale:self->mScale_];
|
||||
self->mFontSize_ = data->fontSize;
|
||||
[self->mFontContext_ addObject:data];
|
||||
self->topFont_ = data;
|
||||
}
|
||||
|
||||
- (void)pushContext:(RNSVGGroup*)node
|
||||
font:(NSDictionary*)font {
|
||||
pushNodeAndFont(self, node, font);
|
||||
pushIndices(self);
|
||||
}
|
||||
|
||||
- (void)pushContext:(RNSVGText*)node
|
||||
font:(NSDictionary*)font
|
||||
x:(NSArray*)x
|
||||
y:(NSArray*)y
|
||||
deltaX:(NSArray*)deltaX
|
||||
deltaY:(NSArray*)deltaY
|
||||
rotate:(NSArray*)rotate {
|
||||
pushNodeAndFont(self, (RNSVGGroup*)node, font);
|
||||
if (x != nil && [x count] != 0) {
|
||||
mXsIndex_++;
|
||||
mXIndex_ = -1;
|
||||
@@ -191,28 +292,33 @@
|
||||
mRs_ = [rotate valueForKeyPath:@"self.doubleValue"];
|
||||
[mRsContext_ addObject:mRs_];
|
||||
}
|
||||
GlyphContext_pushIndices(self);
|
||||
pushIndices(self);
|
||||
}
|
||||
|
||||
- (void)popContext {
|
||||
[mFontContext_ removeLastObject];
|
||||
[mXsIndices_ removeLastObject];
|
||||
[mYsIndices_ removeLastObject];
|
||||
[mDXsIndices_ removeLastObject];
|
||||
[mDYsIndices_ removeLastObject];
|
||||
[mRsIndices_ removeLastObject];
|
||||
[mXsIndices_ removeLastObject];
|
||||
[mYsIndices_ removeLastObject];
|
||||
[mDXsIndices_ removeLastObject];
|
||||
[mDYsIndices_ removeLastObject];
|
||||
[mRsIndices_ removeLastObject];
|
||||
|
||||
mTop_--;
|
||||
|
||||
long x = mXsIndex_;
|
||||
long y = mYsIndex_;
|
||||
long dx = mDXsIndex_;
|
||||
long dy = mDYsIndex_;
|
||||
long r = mRsIndex_;
|
||||
|
||||
topFont_ = [mFontContext_ lastObject];
|
||||
|
||||
mXsIndex_ = [[mXsIndices_ lastObject] longValue];
|
||||
mYsIndex_ = [[mYsIndices_ lastObject] longValue];
|
||||
mDXsIndex_ = [[mDXsIndices_ lastObject] longValue];
|
||||
mDYsIndex_ = [[mDYsIndices_ lastObject] longValue];
|
||||
mRsIndex_ = [[mRsIndices_ lastObject] longValue];
|
||||
|
||||
if (x != mXsIndex_) {
|
||||
[mXsContext_ removeObjectAtIndex:x];
|
||||
mXs_ = [mXsContext_ objectAtIndex:mXsIndex_];
|
||||
@@ -240,17 +346,50 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)incrementIndicesWithNSArray:(NSMutableArray *)indices
|
||||
withLong:(long)topIndex {
|
||||
GlyphContext_incrementIndicesWithNSArray_withLong_(indices, topIndex);
|
||||
void incrementIndices(NSMutableArray *indices, long topIndex) {
|
||||
for (long index = topIndex; index >= 0; index--) {
|
||||
long xIndex = [[indices objectAtIndex:index] longValue];
|
||||
[indices setObject:[NSNumber numberWithLong:xIndex + 1] atIndexedSubscript:index];
|
||||
}
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/SVG11/text.html#FontSizeProperty
|
||||
|
||||
/**
|
||||
* Get font size from context.
|
||||
* <p>
|
||||
* ‘font-size’
|
||||
* Value: < absolute-size > | < relative-size > | < length > | < percentage > | inherit
|
||||
* Initial: medium
|
||||
* Applies to: text content elements
|
||||
* Inherited: yes, the computed value is inherited
|
||||
* Percentages: refer to parent element's font size
|
||||
* Media: visual
|
||||
* Animatable: yes
|
||||
* <p>
|
||||
* This property refers to the size of the font from baseline to
|
||||
* baseline when multiple lines of text are set solid in a multiline
|
||||
* layout environment.
|
||||
* <p>
|
||||
* For SVG, if a < length > is provided without a unit identifier
|
||||
* (e.g., an unqualified number such as 128), the SVG user agent
|
||||
* processes the < length > as a height value in the current user
|
||||
* coordinate system.
|
||||
* <p>
|
||||
* If a < length > is provided with one of the unit identifiers
|
||||
* (e.g., 12pt or 10%), then the SVG user agent converts the
|
||||
* < length > into a corresponding value in the current user
|
||||
* coordinate system by applying the rules described in Units.
|
||||
* <p>
|
||||
* Except for any additional information provided in this specification,
|
||||
* the normative definition of the property is in CSS2 ([CSS2], section 15.2.4).
|
||||
*/
|
||||
- (double)getFontSize {
|
||||
return mFontSize_;
|
||||
}
|
||||
|
||||
- (double)nextXWithDouble:(double)advance {
|
||||
GlyphContext_incrementIndicesWithNSArray_withLong_(mXIndices_, mXsIndex_);
|
||||
incrementIndices(mXIndices_, mXsIndex_);
|
||||
long nextIndex = mXIndex_ + 1;
|
||||
if (nextIndex < [mXs_ count]) {
|
||||
mDX_ = 0;
|
||||
@@ -267,7 +406,7 @@
|
||||
}
|
||||
|
||||
- (double)nextY {
|
||||
GlyphContext_incrementIndicesWithNSArray_withLong_(mYIndices_, mYsIndex_);
|
||||
incrementIndices(mYIndices_, mYsIndex_);
|
||||
long nextIndex = mYIndex_ + 1;
|
||||
if (nextIndex < [mYs_ count]) {
|
||||
mDY_ = 0;
|
||||
@@ -283,7 +422,7 @@
|
||||
}
|
||||
|
||||
- (double)nextDeltaX {
|
||||
GlyphContext_incrementIndicesWithNSArray_withLong_(mDXIndices_, mDXsIndex_);
|
||||
incrementIndices(mDXIndices_, mDXsIndex_);
|
||||
long nextIndex = mDXIndex_ + 1;
|
||||
if (nextIndex < [mDXs_ count]) {
|
||||
mDXIndex_ = nextIndex;
|
||||
@@ -299,7 +438,7 @@
|
||||
}
|
||||
|
||||
- (double)nextDeltaY {
|
||||
GlyphContext_incrementIndicesWithNSArray_withLong_(mDYIndices_, mDYsIndex_);
|
||||
incrementIndices(mDYIndices_, mDYsIndex_);
|
||||
long nextIndex = mDYIndex_ + 1;
|
||||
if (nextIndex < [mDYs_ count]) {
|
||||
mDYIndex_ = nextIndex;
|
||||
@@ -315,7 +454,7 @@
|
||||
}
|
||||
|
||||
- (NSNumber*)nextRotation {
|
||||
GlyphContext_incrementIndicesWithNSArray_withLong_(mRIndices_, mRsIndex_);
|
||||
incrementIndices(mRIndices_, mRsIndex_);
|
||||
long nextIndex = mRIndex_ + 1;
|
||||
long count = [mRs_ count];
|
||||
if (nextIndex < count) {
|
||||
@@ -333,104 +472,4 @@
|
||||
- (float)getHeight {
|
||||
return mHeight_;
|
||||
}
|
||||
|
||||
void GlyphContext_pushIndices(GlyphContext *self) {
|
||||
[self->mXsIndices_ addObject:[NSNumber numberWithLong:self->mXsIndex_]];
|
||||
[self->mYsIndices_ addObject:[NSNumber numberWithLong:self->mYsIndex_]];
|
||||
[self->mDXsIndices_ addObject:[NSNumber numberWithLong:self->mDXsIndex_]];
|
||||
[self->mDYsIndices_ addObject:[NSNumber numberWithLong:self->mDYsIndex_]];
|
||||
[self->mRsIndices_ addObject:[NSNumber numberWithLong:self->mRsIndex_]];
|
||||
}
|
||||
|
||||
void GlyphContext_initWithFloat_withFloat_withFloat_(GlyphContext *self, float scale_, float width, float height) {
|
||||
self->mFontContext_ = [[NSMutableArray alloc]init];
|
||||
self->mXsContext_ = [[NSMutableArray alloc]init];
|
||||
self->mYsContext_ = [[NSMutableArray alloc]init];
|
||||
self->mDXsContext_ = [[NSMutableArray alloc]init];
|
||||
self->mDYsContext_ = [[NSMutableArray alloc]init];
|
||||
self->mRsContext_ = [[NSMutableArray alloc]init];
|
||||
self->mXIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mYIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mDXIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mDYIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mRIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mXsIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mYsIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mDXsIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mDYsIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mRsIndices_ = [[NSMutableArray alloc]init];
|
||||
self->mFontSize_ = FontData_DEFAULT_FONT_SIZE;
|
||||
self->topFont_ = [FontData Defaults];
|
||||
self->mXs_ = [[NSArray alloc]init];
|
||||
self->mYs_ = [[NSArray alloc]init];
|
||||
self->mDXs_ = [[NSArray alloc]init];
|
||||
self->mDYs_ = [[NSArray alloc]init];
|
||||
self->mRs_ = [[NSArray alloc]initWithObjects:@0, nil];
|
||||
self->mXIndex_ = -1;
|
||||
self->mYIndex_ = -1;
|
||||
self->mDXIndex_ = -1;
|
||||
self->mDYIndex_ = -1;
|
||||
self->mRIndex_ = -1;
|
||||
self->mScale_ = scale_;
|
||||
self->mWidth_ = width;
|
||||
self->mHeight_ = height;
|
||||
[self->mXsContext_ addObject:self->mXs_];
|
||||
[self->mYsContext_ addObject:self->mYs_];
|
||||
[self->mDXsContext_ addObject:self->mDXs_];
|
||||
[self->mDYsContext_ addObject:self->mDYs_];
|
||||
[self->mRsContext_ addObject:self->mRs_];
|
||||
[self->mXIndices_ addObject:[NSNumber numberWithLong:self->mXIndex_]];
|
||||
[self->mYIndices_ addObject:[NSNumber numberWithLong:self->mYIndex_]];
|
||||
[self->mDXIndices_ addObject:[NSNumber numberWithLong:self->mDXIndex_]];
|
||||
[self->mDYIndices_ addObject:[NSNumber numberWithLong:self->mDYIndex_]];
|
||||
[self->mRIndices_ addObject:[NSNumber numberWithLong:self->mRIndex_]];
|
||||
[self->mFontContext_ addObject:self->topFont_];
|
||||
GlyphContext_pushIndices(self);
|
||||
}
|
||||
|
||||
void GlyphContext_reset(GlyphContext *self) {
|
||||
self->mXsIndex_ = self->mYsIndex_ = self->mDXsIndex_ = self->mDYsIndex_ = self->mRsIndex_ = 0;
|
||||
self->mXIndex_ = self->mYIndex_ = self->mDXIndex_ = self->mDYIndex_ = self->mRIndex_ = -1;
|
||||
self->mX_ = self->mY_ = self->mDX_ = self->mDY_ = 0;
|
||||
}
|
||||
|
||||
FontData *GlyphContext_getTopOrParentFontWithRNSVGGroup_(GlyphContext *self, RNSVGGroup* child) {
|
||||
if (self->mTop_ > 0) {
|
||||
return self->topFont_;
|
||||
}
|
||||
else {
|
||||
RNSVGGroup* parentRoot = [child getParentTextRoot];
|
||||
FontData* Defaults = [FontData Defaults];
|
||||
while (parentRoot != nil) {
|
||||
FontData *map = [[parentRoot getGlyphContext] getFont];
|
||||
if (map != Defaults) {
|
||||
return map;
|
||||
}
|
||||
parentRoot = [parentRoot getParentTextRoot];
|
||||
}
|
||||
return Defaults;
|
||||
}
|
||||
}
|
||||
|
||||
void GlyphContext_pushNodeAndFontWithRNSVGGroup_withNSDictionary_(GlyphContext *self, RNSVGGroup* node, NSDictionary* font) {
|
||||
FontData *parent = GlyphContext_getTopOrParentFontWithRNSVGGroup_(self, node);
|
||||
self->mTop_++;
|
||||
if (font == nil) {
|
||||
[self->mFontContext_ addObject:parent];
|
||||
return;
|
||||
}
|
||||
FontData *data = [FontData initWithNSDictionary:font
|
||||
parent:parent
|
||||
scale:self->mScale_];
|
||||
self->mFontSize_ = data->fontSize;
|
||||
[self->mFontContext_ addObject:data];
|
||||
self->topFont_ = data;
|
||||
}
|
||||
|
||||
void GlyphContext_incrementIndicesWithNSArray_withLong_(NSMutableArray *indices, long topIndex) {
|
||||
for (long index = topIndex; index >= 0; index--) {
|
||||
long xIndex = [[indices objectAtIndex:index] longValue];
|
||||
[indices setObject:[NSNumber numberWithLong:xIndex + 1] atIndexedSubscript:index];
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
+75
-61
@@ -12,6 +12,8 @@
|
||||
#import "RNSVGTextPath.h"
|
||||
#import "FontData.h"
|
||||
|
||||
NSCharacterSet *separators = nil;
|
||||
|
||||
@implementation RNSVGTSpan
|
||||
{
|
||||
CGFloat startOffset;
|
||||
@@ -23,6 +25,17 @@
|
||||
bool isClosed;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (separators == nil) {
|
||||
separators = [NSCharacterSet whitespaceCharacterSet];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setContent:(NSString *)content
|
||||
{
|
||||
if (content == _content) {
|
||||
@@ -517,8 +530,8 @@
|
||||
double totalHeight = top + bottom;
|
||||
double baselineShift = 0;
|
||||
// TODO, alignmentBaseline and baselineShift are always nil for some reason?
|
||||
NSString *baselineShiftString = [self baselineShift];
|
||||
enum AlignmentBaseline baseline = AlignmentBaselineFromString([self alignmentBaseline]);
|
||||
NSString *baselineShiftString = [self getBaselineShift];
|
||||
enum AlignmentBaseline baseline = AlignmentBaselineFromString([self getAlignmentBaseline]);
|
||||
if (baseline != AlignmentBaselineBaseline) {
|
||||
// TODO alignment-baseline, test / verify behavior
|
||||
// TODO get per glyph baselines from font baseline table, for high-precision alignment
|
||||
@@ -602,72 +615,72 @@
|
||||
baselineShift = top;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
2.2.2. Alignment Shift: baseline-shift longhand
|
||||
}
|
||||
/*
|
||||
2.2.2. Alignment Shift: baseline-shift longhand
|
||||
|
||||
This property specifies by how much the box is shifted up from its alignment point.
|
||||
It does not apply when alignment-baseline is top or bottom.
|
||||
This property specifies by how much the box is shifted up from its alignment point.
|
||||
It does not apply when alignment-baseline is top or bottom.
|
||||
|
||||
Authors should use the vertical-align shorthand instead of this property.
|
||||
Authors should use the vertical-align shorthand instead of this property.
|
||||
|
||||
Values have the following meanings:
|
||||
Values have the following meanings:
|
||||
|
||||
<length>
|
||||
Raise (positive value) or lower (negative value) by the specified length.
|
||||
<percentage>
|
||||
Raise (positive value) or lower (negative value) by the specified percentage of the line-height.
|
||||
TODO sub
|
||||
Lower by the offset appropriate for subscripts of the parent’s box.
|
||||
(The UA should use the parent’s font data to find this offset whenever possible.)
|
||||
TODO super
|
||||
Raise by the offset appropriate for superscripts of the parent’s box.
|
||||
(The UA should use the parent’s font data to find this offset whenever possible.)
|
||||
<length>
|
||||
Raise (positive value) or lower (negative value) by the specified length.
|
||||
<percentage>
|
||||
Raise (positive value) or lower (negative value) by the specified percentage of the line-height.
|
||||
TODO sub
|
||||
Lower by the offset appropriate for subscripts of the parent’s box.
|
||||
(The UA should use the parent’s font data to find this offset whenever possible.)
|
||||
TODO super
|
||||
Raise by the offset appropriate for superscripts of the parent’s box.
|
||||
(The UA should use the parent’s font data to find this offset whenever possible.)
|
||||
|
||||
User agents may additionally support the keyword baseline as computing to 0
|
||||
if is necessary for them to support legacy SVG content.
|
||||
Issue: We would prefer to remove this,
|
||||
and are looking for feedback from SVG user agents as to whether it’s necessary.
|
||||
User agents may additionally support the keyword baseline as computing to 0
|
||||
if is necessary for them to support legacy SVG content.
|
||||
Issue: We would prefer to remove this,
|
||||
and are looking for feedback from SVG user agents as to whether it’s necessary.
|
||||
|
||||
https://www.w3.org/TR/css-inline-3/#propdef-baseline-shift
|
||||
*/
|
||||
if (baselineShiftString != nil && fontData != nil) {
|
||||
switch (baseline) {
|
||||
case AlignmentBaselineTop:
|
||||
case AlignmentBaselineBottom:
|
||||
break;
|
||||
|
||||
default:
|
||||
if ([baselineShiftString isEqualToString:@"sub"]) {
|
||||
// TODO
|
||||
NSDictionary* tables = [fontData objectForKey:@"tables"];
|
||||
NSNumber* unitsPerEm = [fontData objectForKey:@"unitsPerEm"];
|
||||
NSDictionary* os2 = [tables objectForKey:@"os2"];
|
||||
NSNumber* ySubscriptYOffset = [os2 objectForKey:@"ySubscriptYOffset"];
|
||||
if (ySubscriptYOffset) {
|
||||
double subOffset = [ySubscriptYOffset doubleValue];
|
||||
baselineShift += fontSize * subOffset / [unitsPerEm doubleValue];
|
||||
}
|
||||
} else if ([baselineShiftString isEqualToString:@"super"]) {
|
||||
// TODO
|
||||
NSDictionary* tables = [fontData objectForKey:@"tables"];
|
||||
NSNumber* unitsPerEm = [fontData objectForKey:@"unitsPerEm"];
|
||||
NSDictionary* os2 = [tables objectForKey:@"os2"];
|
||||
NSNumber* ySuperscriptYOffset = [os2 objectForKey:@"ySuperscriptYOffset"];
|
||||
if (ySuperscriptYOffset) {
|
||||
double superOffset = [ySuperscriptYOffset doubleValue];
|
||||
baselineShift -= fontSize * superOffset / [unitsPerEm doubleValue];
|
||||
}
|
||||
} else if ([baselineShiftString isEqualToString:@"baseline"]) {
|
||||
} else {
|
||||
baselineShift -= [PropHelper fromRelativeWithNSString:baselineShiftString
|
||||
relative:fontSize
|
||||
offset:0
|
||||
scale:1
|
||||
fontSize:fontSize];
|
||||
https://www.w3.org/TR/css-inline-3/#propdef-baseline-shift
|
||||
*/
|
||||
if (baselineShiftString != nil && ![baselineShiftString isEqualToString:@""]) {
|
||||
switch (baseline) {
|
||||
case AlignmentBaselineTop:
|
||||
case AlignmentBaselineBottom:
|
||||
break;
|
||||
|
||||
default:
|
||||
if (fontData != nil && [baselineShiftString isEqualToString:@"sub"]) {
|
||||
// TODO
|
||||
NSDictionary* tables = [fontData objectForKey:@"tables"];
|
||||
NSNumber* unitsPerEm = [fontData objectForKey:@"unitsPerEm"];
|
||||
NSDictionary* os2 = [tables objectForKey:@"os2"];
|
||||
NSNumber* ySubscriptYOffset = [os2 objectForKey:@"ySubscriptYOffset"];
|
||||
if (ySubscriptYOffset) {
|
||||
double subOffset = [ySubscriptYOffset doubleValue];
|
||||
baselineShift += fontSize * subOffset / [unitsPerEm doubleValue];
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (fontData != nil && [baselineShiftString isEqualToString:@"super"]) {
|
||||
// TODO
|
||||
NSDictionary* tables = [fontData objectForKey:@"tables"];
|
||||
NSNumber* unitsPerEm = [fontData objectForKey:@"unitsPerEm"];
|
||||
NSDictionary* os2 = [tables objectForKey:@"os2"];
|
||||
NSNumber* ySuperscriptYOffset = [os2 objectForKey:@"ySuperscriptYOffset"];
|
||||
if (ySuperscriptYOffset) {
|
||||
double superOffset = [ySuperscriptYOffset doubleValue];
|
||||
baselineShift -= fontSize * superOffset / [unitsPerEm doubleValue];
|
||||
}
|
||||
} else if ([baselineShiftString isEqualToString:@"baseline"]) {
|
||||
} else {
|
||||
baselineShift -= [PropHelper fromRelativeWithNSString:baselineShiftString
|
||||
relative:fontSize
|
||||
offset:0
|
||||
scale:1
|
||||
fontSize:fontSize];
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
int i = -1;
|
||||
@@ -709,7 +722,8 @@
|
||||
kerning = kerned - charWidth;
|
||||
}
|
||||
|
||||
bool isWordSeparator = false;
|
||||
char currentChar = [str characterAtIndex:i];
|
||||
bool isWordSeparator = [separators characterIsMember:currentChar];
|
||||
double wordSpace = isWordSeparator ? wordSpacing : 0;
|
||||
double spacing = wordSpace + letterSpacing;
|
||||
double advance = charWidth + spacing;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "RNSVGGroup.h"
|
||||
#import "RNSVGTextAnchor.h"
|
||||
#import "AlignmentBaseline.h"
|
||||
|
||||
@interface RNSVGText : RNSVGGroup
|
||||
|
||||
@@ -25,5 +26,7 @@
|
||||
- (void)releaseCachedPath;
|
||||
- (CGPathRef)getGroupPath:(CGContextRef)context;
|
||||
- (CTFontRef)getFontFromContext;
|
||||
- (NSString*) getAlignmentBaseline;
|
||||
- (NSString*) getBaselineShift;
|
||||
|
||||
@end
|
||||
|
||||
+49
-2
@@ -91,6 +91,54 @@
|
||||
return _textRoot;
|
||||
}
|
||||
|
||||
- (NSString*) getAlignmentBaseline
|
||||
{
|
||||
if (self.alignmentBaseline != nil) {
|
||||
return self.alignmentBaseline;
|
||||
}
|
||||
UIView* parent = [self superview];
|
||||
while (parent != nil) {
|
||||
if ([parent isKindOfClass:[RNSVGText class]]) {
|
||||
RNSVGText* node = (RNSVGText*)parent;
|
||||
NSString* baseline = node.alignmentBaseline;
|
||||
if (baseline != nil) {
|
||||
self.alignmentBaseline = baseline;
|
||||
return baseline;
|
||||
}
|
||||
}
|
||||
parent = [parent superview];
|
||||
}
|
||||
if (self.alignmentBaseline == nil) {
|
||||
self.alignmentBaseline = AlignmentBaselineStrings[0];
|
||||
}
|
||||
return self.alignmentBaseline;
|
||||
}
|
||||
|
||||
- (NSString*) getBaselineShift
|
||||
{
|
||||
if (self.baselineShift != nil) {
|
||||
return self.baselineShift;
|
||||
}
|
||||
if (self.baselineShift == nil) {
|
||||
UIView* parent = [self superview];
|
||||
while (parent != nil) {
|
||||
if ([parent isKindOfClass:[RNSVGText class]]) {
|
||||
RNSVGText* node = (RNSVGText*)parent;
|
||||
NSString* baselineShift = node.baselineShift;
|
||||
if (baselineShift != nil) {
|
||||
self.baselineShift = baselineShift;
|
||||
return baselineShift;
|
||||
}
|
||||
}
|
||||
parent = [parent superview];
|
||||
}
|
||||
}
|
||||
if (self.baselineShift == nil) {
|
||||
self.baselineShift = @"";
|
||||
}
|
||||
return self.baselineShift;
|
||||
}
|
||||
|
||||
- (GlyphContext *)getGlyphContext
|
||||
{
|
||||
return _glyphContext;
|
||||
@@ -98,8 +146,7 @@
|
||||
|
||||
- (void)pushGlyphContext
|
||||
{
|
||||
[[[self getTextRoot] getGlyphContext] pushContextwithRNSVGText:self
|
||||
reset:false
|
||||
[[[self getTextRoot] getGlyphContext] pushContext:self
|
||||
font:self.font
|
||||
x:self.positionX
|
||||
y:self.positionY
|
||||
|
||||
Reference in New Issue
Block a user