31 @global _MakeRangeFromAbs
34 function _isNewlineCharacter(chr)
36 return (chr ===
'\n' || chr ===
'\r');
39 function _RectEqualToRectHorizontally(lhsRect, rhsRect)
41 return (lhsRect.origin.x == rhsRect.origin.x &&
42 lhsRect.size.width == rhsRect.size.width &&
43 lhsRect.size.height == rhsRect.size.height);
46 _oncontextmenuhandler =
function () {
return false; };
54 Class _lineFragmentFactory;
61 id _extraLineFragment;
65 BOOL _isValidatingLayoutAndGlyphs;
66 CPRange _removeInvalidLineFragmentsRange;
71 #pragma mark Init methods 75 if (
self = [super
init])
85 _isValidatingLayoutAndGlyphs = NO;
86 _lineFragmentFactory = [_CPLineFragment class];
92 [_textStorage addLayoutManager:self];
97 #pragma mark Text containes method 101 [_textContainers insertObject:aContainer atIndex:index];
107 [_textContainers addObject:aContainer];
111 - (void)removeTextContainerAtIndex:(
int)index
113 var container = [_textContainers objectAtIndex:index];
114 [container setLayoutManager:nil];
115 [_textContainers removeObjectAtIndex:index];
119 - (int)numberOfGlyphs
121 return [_textStorage length];
124 - (int)numberOfCharacters
126 return [_textStorage length];
131 return [_textContainers[0] textView];
137 return [[_textContainers objectAtIndex:0] textView];
140 - (BOOL)layoutManagerOwnsFirstResponderInWindow:(
CPWindow)aWindow
143 c = [_textContainers count];
145 for (var i = 0; i < c; i++)
147 if ([_textContainers[i] textView] === firstResponder)
154 - (CGRect)boundingRectForGlyphRange:(CGRange)aRange inTextContainer:(
CPTextContainer)container
156 if (![
self numberOfGlyphs])
157 return CGRectMake(0, 0, 1, 12);
159 if (
CPMaxRange(aRange) > [
self numberOfGlyphs])
160 aRange =
CPMakeRange([
self numberOfGlyphs] - 1, 1);
162 var fragments = _objectsInRange(_lineFragments, aRange),
164 c = [fragments count];
166 for (var i = 0; i < c; i++)
168 var fragment = fragments[i];
170 if (fragment._textContainer === container)
172 var frames = [fragment glyphFrames],
173 l = frames ? frames.length : 0;
175 for (var j = 0; j < l; j++)
180 rect = CGRectCreateCopy(frames[j]);
182 rect = CGRectUnion(rect, frames[j]);
188 return rect ? rect : CGRectMakeZero();
194 c = [_lineFragments count];
196 for (var i = 0; i < c; i++)
198 var fragment = _lineFragments[i];
200 if (fragment._textContainer === aTextContainer)
212 - (void)_removeInvalidLineFragments
214 _lineFragmentsForRescue = [_lineFragments copy];
215 [_lineFragmentsForRescue makeObjectsPerformSelector:@selector(_deinvalidate)];
217 if (_removeInvalidLineFragmentsRange && _removeInvalidLineFragmentsRange.length && _lineFragments.length)
220 [_lineFragments removeObjectsInRange:_removeInvalidLineFragmentsRange];
221 [[_lineFragmentsForRescue subarrayWithRange:_removeInvalidLineFragmentsRange] makeObjectsPerformSelector:@selector(invalidate)];
228 var l = _lineFragmentsForRescue? _lineFragmentsForRescue.length : 0;
230 for (var i = 0; i < l; i++)
232 if (_lineFragmentsForRescue[i]._isInvalid)
233 [_lineFragmentsForRescue[i] _removeFromDOM];
237 - (void)_validateLayoutAndGlyphs
239 if (_isValidatingLayoutAndGlyphs)
242 _isValidatingLayoutAndGlyphs = YES;
246 l = _lineFragments.length;
250 for (var i = 0; i < l; i++)
252 if (_lineFragments[i]._isInvalid)
254 startIndex = _lineFragments[i]._range.location;
255 removeRange.location = i;
256 removeRange.length = l - i;
262 if (startIndex ==
CPNotFound &&
CPMaxRange (_lineFragments[l - 1]._range) < [_textStorage length])
263 startIndex =
CPMaxRange(_lineFragments[l - 1]._range);
273 _isValidatingLayoutAndGlyphs = NO;
277 if (removeRange.length)
282 [
self setExtraLineFragmentRect:CGRectMake(0, 0) usedRect:CGRectMake(0, 0) textContainer:nil];
285 [_typesetter layoutGlyphsInLayoutManager:self startingAtGlyphIndex:startIndex maxNumberOfLineFragments:-1 nextGlyphIndex:nil];
291 _isValidatingLayoutAndGlyphs = NO;
294 - (BOOL)_rescuingInvalidFragmentsWasPossibleForGlyphRange:(CPRange)aRange
296 var l = _lineFragments.length,
297 location = aRange.location,
302 for (; targetLine < l; targetLine++)
314 if (!_lineFragmentsForRescue[targetLine])
317 var startLineForDOMRemoval = targetLine,
319 newLineFragment= _lineFragments[targetLine],
320 oldLineFragment = _lineFragmentsForRescue[targetLine],
321 oldLength =
CPMaxRange([_lineFragmentsForRescue lastObject]._range),
322 newLength = [[_textStorage string].length],
328 if (![oldLineFragment isVisuallyIdenticalToFragment:newLineFragment])
333 if (newLength < oldLength && oldLineFragment._range.length == 1 && newLineFragment._range.length > 1 && newLineFragment._range.location === oldLineFragment._range.location && oldLineFragment._isLast)
341 if (newLength > oldLength && newLineFragment._range.length == 1 && oldLineFragment._range.length > 1 && newLineFragment._range.location === oldLineFragment._range.location && newLineFragment._isLast)
344 startLineForDOMRemoval--;
351 var rangeOffset =
CPMaxRange(_lineFragments[targetLine]._range) -
CPMaxRange(_lineFragmentsForRescue[startLineForDOMRemoval]._range);
353 if (ABS(rangeOffset) !== ABS(newLength - oldLength))
356 var verticalOffset = _lineFragments[targetLine]._fragmentRect.origin.y - _lineFragmentsForRescue[startLineForDOMRemoval]._fragmentRect.origin.y,
357 l = _lineFragmentsForRescue.length,
358 newTargetLine = startLineForDOMRemoval + removalSkip;
360 for (; newTargetLine < l; newTargetLine++)
362 _lineFragmentsForRescue[newTargetLine]._isInvalid = NO;
363 [_lineFragmentsForRescue[newTargetLine] _relocateVerticallyByY:verticalOffset rangeOffset:rangeOffset];
364 _lineFragments.push(_lineFragmentsForRescue[newTargetLine]);
371 - (void)invalidateDisplayForGlyphRange:(CPRange)range
373 var lineFragments = _objectsInRange(_lineFragments, range);
375 for (var i = 0; i < lineFragments.length; i++)
376 [[lineFragments[i]._textContainer textView] setNeedsDisplayInRect:lineFragments[i]._fragmentRect];
379 - (void)invalidateLayoutForCharacterRange:(CPRange)aRange isSoft:(BOOL)flag actualCharacterRange:(CPRangePointer)actualCharRange
381 var firstFragmentIndex = _lineFragments.length ? [_lineFragments _indexOfObject: aRange.location sortedByFunction:_sortRange context:nil] :
CPNotFound;
385 if (_lineFragments.length)
387 firstFragmentIndex = _lineFragments.length - 1;
393 actualCharRange.length = aRange.length;
394 actualCharRange.location = 0;
402 firstFragmentIndex = firstFragmentIndex + (firstFragmentIndex ? -1 : 0);
405 var fragment = _lineFragments[firstFragmentIndex],
408 fragment._isInvalid = YES;
411 for (var i = firstFragmentIndex + 1; i < _lineFragments.length; i++)
413 _lineFragments[i]._isInvalid = YES;
422 actualCharRange.length = range.length;
423 actualCharRange.location = range.location;
427 - (void)textStorage:(
CPTextStorage)textStorage edited:(
unsigned)mask range:(CPRange)charRange changeInLength:(
int)delta invalidatedRange:(CPRange)invalidatedRange
433 [
self _validateLayoutAndGlyphs];
437 - (CPRange)glyphRangeForBoundingRect:(CGRect)aRect inTextContainer:(
CPTextContainer)container
439 var c = [_lineFragments count],
442 for (var i = 0; i < c; i++)
444 var fragment = _lineFragments[i];
446 if (fragment._textContainer === container)
448 if (CGRectContainsRect(aRect, fragment._fragmentRect))
458 frames = [fragment glyphFrames];
460 for (var j = 0; j < frames.length; j++)
462 if (CGRectIntersectsRect(aRect, frames[j]))
465 glyphRange.location = fragment._range.location + j;
485 - (void)drawBackgroundForGlyphRange:(CPRange)aRange atPoint:(CGPoint)aPoint
490 - (void)drawUnderlineForGlyphRange:(CPRange)glyphRange
491 underlineType:(
int)underlineVal
492 baselineOffset:(
float)baselineOffset
493 lineFragmentRect:(CGRect)lineFragmentRect
494 lineFragmentGlyphRange:(CPRange)lineGlyphRange
495 containerOrigin:(CGPoint)containerOrigin
500 - (void)drawGlyphsForGlyphRange:(CPRange)aRange atPoint:(CGPoint)aPoint
502 var lineFragments = _objectsInRange(_lineFragments, aRange);
504 if (!lineFragments.length)
508 l = lineFragments.length,
512 for (lineFragmentIndex = 0; lineFragmentIndex < l; lineFragmentIndex++)
514 var currentFragment = lineFragments[lineFragmentIndex];
515 [currentFragment drawInContext:ctx atPoint:aPoint forRange:paintedRange];
519 - (unsigned)glyphIndexForPoint:(CGPoint)point inTextContainer:(
CPTextContainer)container fractionOfDistanceThroughGlyph:(FloatArray)partialFraction
521 var c = [_lineFragments count];
523 for (var i = 0; i < c; i++)
525 var fragment = _lineFragments[i];
527 if (fragment._textContainer === container)
529 var frames = [fragment glyphFrames],
530 len = fragment._range.length;
532 for (var j = 0; j < len; j++)
534 if (CGRectContainsPoint(frames[j], point))
537 partialFraction[0] = (point.x - frames[j].origin.x) / frames[j].size.width;
539 return fragment._range.location + j;
546 if ([[_textStorage
string] length])
548 for (var i = 0; i < c; i++)
550 var fragment = _lineFragments[i];
552 if (fragment._textContainer === container)
555 if (fragment._range.length > 0 && point.y > fragment._fragmentRect.origin.y &&
556 point.y <= fragment._fragmentRect.origin.y + fragment._fragmentRect.size.height)
559 if (i < c - 1 && _lineFragments[i + 1]._fragmentRect.origin.y === fragment._fragmentRect.origin.y)
563 lastFrame = [fragment glyphFrames][fragment._range.length - 1],
564 firstFrame = [fragment glyphFrames][0];
567 if (_isNewlineCharacter([[_textStorage
string] characterAtIndex:nlLoc > 0 ? nlLoc - 1 : 0]))
571 if (point.x > CGRectGetMaxX(lastFrame))
574 else if (point.x <= CGRectGetMinX(firstFrame))
575 return fragment._range.location;
583 return point.y > 0 ? [[_textStorage string] length] : 0;
586 - (unsigned)glyphIndexForPoint:(CGPoint)point inTextContainer:(
CPTextContainer)container
591 - (void)_setAttributes:(
CPDictionary)attributes toTemporaryAttributes:(_CPTemporaryAttributes)tempAttributes
593 tempAttributes._attributes = attributes;
596 - (void)_addAttributes:(
CPDictionary)attributes toTemporaryAttributes:(_CPTemporaryAttributes)tempAttributes
598 [tempAttributes._attributes addEntriesFromDictionary:attributes];
601 - (void)_handleTemporaryAttributes:(
CPDictionary)attributes forCharacterRange:(CPRange)charRange withSelector:(
SEL)attributesOperation
606 - (void)setTemporaryAttributes:(
CPDictionary)attributes forCharacterRange:(CPRange)charRange
608 [
self _handleTemporaryAttributes:attributes forCharacterRange:charRange withSelector:@selector(_setAttributes:toTemporaryAttributes:)];
611 - (void)addTemporaryAttributes:(
CPDictionary)attributes forCharacterRange:(CPRange)charRange
613 [
self _handleTemporaryAttributes:attributes forCharacterRange:charRange withSelector:@selector(_addAttributes:toTemporaryAttributes:)];
616 - (void)removeTemporaryAttribute:(
CPString)attributeName forCharacterRange:(CPRange)charRange
621 - (
CPDictionary)temporaryAttributesAtCharacterIndex:(
unsigned)index effectiveRange:(CPRangePointer)effectiveRange
631 - (void)_appendNewLineFragmentInTextContainer:(
CPTextContainer)aTextContainer forGlyphRange:(CPRange)glyphRange
633 _lineFragments.push([[_lineFragmentFactory alloc] initWithRange:glyphRange textContainer:aTextContainer textStorage:_textStorage]);
636 - (void)setTextContainer:(
CPTextContainer)aTextContainer forGlyphRange:(CPRange)glyphRange
638 var fragments = _objectsInRange(_lineFragments, glyphRange),
639 l = fragments.length;
641 for (var i = 0; i < l; i++)
642 fragments[i]._textContainer = aTextContainer;
645 - (id)_lineFragmentForLocation:(
unsigned) aLoc
647 var fragments = _objectsInRange(_lineFragments,
CPMakeRange(aLoc, 0)),
648 l = fragments.length;
656 - (id)_firstLineFragmentForLineFromLocation:(
unsigned)location
658 var l = _lineFragments.length;
660 for (var i = 0; i < l; i++)
666 while (--j > 0 && !_lineFragments[j]._isLast)
671 return _lineFragments[j + 1];
677 - (id)_lastLineFragmentForLineFromLocation:(
unsigned)location
679 var l = _lineFragments.length;
681 for (var i = 0; i < l; i++)
687 while (!_lineFragments[j]._isLast)
690 return _lineFragments[j];
697 - (double)_characterOffsetAtLocation:(
unsigned)location
699 var lineFragment = _objectWithLocationInRange(_lineFragments, location);
704 var index = location - lineFragment._range.location;
706 return lineFragment._glyphsOffsets[index];
709 - (double)_descentAtLocation:(
unsigned)location
711 var lineFragment = _objectWithLocationInRange(_lineFragments, location);
716 var index = location - lineFragment._range.location;
718 return lineFragment._glyphsFrames[index]._descent;
721 - (void)setLineFragmentRect:(CGRect)fragmentRect forGlyphRange:(CPRange)glyphRange usedRect:(CGRect)usedRect
723 var lineFragment = _objectWithLocationInRange(_lineFragments, glyphRange.location);
727 lineFragment._fragmentRect = CGRectCreateCopy(fragmentRect);
728 lineFragment._usedRect = CGRectCreateCopy(usedRect);
732 - (void)_setAdvancements:(CPArray)someAdvancements forGlyphRange:(CPRange)glyphRange
734 var lineFragment = _objectWithLocationInRange(_lineFragments, glyphRange.location);
737 [lineFragment setAdvancements:someAdvancements];
740 - (void)setLocation:(CGPoint)aPoint forStartOfGlyphRange:(CPRange)glyphRange
742 var lineFragment = _objectWithLocationInRange(_lineFragments, glyphRange.location);
745 lineFragment._location = CGPointCreateCopy(aPoint);
748 - (CGRect)extraLineFragmentRect
750 if (_extraLineFragment)
751 return CGRectCreateCopy(_extraLineFragment._fragmentRect);
753 return CGRectMakeZero();
758 if (_extraLineFragment)
759 return _extraLineFragment._textContainer;
764 - (CGRect)extraLineFragmentUsedRect
766 if (_extraLineFragment)
767 return CGRectCreateCopy(_extraLineFragment._usedRect);
769 return CGRectMakeZero();
772 - (void)setExtraLineFragmentRect:(CGRect)rect usedRect:(CGRect)usedRect textContainer:(
CPTextContainer)textContainer
776 _extraLineFragment = {};
777 _extraLineFragment._fragmentRect = CGRectCreateCopy(rect);
778 _extraLineFragment._usedRect = CGRectCreateCopy(usedRect);
779 _extraLineFragment._textContainer = textContainer;
783 _extraLineFragment = nil;
790 l = _lineFragments.length;
792 for (var i = 0; i < l; i++)
794 if (_lineFragments[i]._textContainer === textContainer)
797 rect = CGRectUnion(rect, _lineFragments[i]._usedRect);
799 rect = CGRectCreateCopy(_lineFragments[i]._usedRect);
803 return rect ? rect : CGRectMakeZero();
806 - (CGRect)lineFragmentRectForGlyphAtIndex:(
unsigned)glyphIndex effectiveRange:(CPRangePointer)effectiveGlyphRange
808 var lineFragment = _objectWithLocationInRange(_lineFragments, glyphIndex);
811 return CGRectMakeZero();
813 if (effectiveGlyphRange)
815 effectiveGlyphRange.location = lineFragment._range.location;
816 effectiveGlyphRange.length = lineFragment._range.length;
819 return CGRectCreateCopy(lineFragment._fragmentRect);
822 - (CGRect)lineFragmentUsedRectForGlyphAtIndex:(
unsigned)glyphIndex effectiveRange:(CPRangePointer)effectiveGlyphRange
824 var lineFragment = _objectWithLocationInRange(_lineFragments, glyphIndex);
827 return CGRectMakeZero();
829 if (effectiveGlyphRange)
831 effectiveGlyphRange.location = lineFragment._range.location;
832 effectiveGlyphRange.length = lineFragment._range.length;
835 return CGRectCreateCopy(lineFragment._usedRect);
838 - (CGPoint)locationForGlyphAtIndex:(
unsigned)index
840 if (_lineFragments.length > 0 && index >= [
self numberOfGlyphs] - 1)
842 var lineFragment= _lineFragments[_lineFragments.length - 1],
843 glyphFrames = [lineFragment glyphFrames];
845 if (glyphFrames.length > 0)
846 return CGPointCreateCopy(glyphFrames[glyphFrames.length - 1].origin);
849 var lineFragment = _objectWithLocationInRange(_lineFragments, index);
853 if (index == lineFragment._range.location)
854 return CGPointCreateCopy(lineFragment._location);
856 var glyphFrames = [lineFragment glyphFrames];
858 return CGPointCreateCopy(glyphFrames[index - lineFragment._range.location].origin);
861 return CGPointMakeZero();
864 - (
CPTextContainer)textContainerForGlyphAtIndex:(
unsigned)index effectiveRange:(CPRangePointer)effectiveGlyphRange withoutAdditionalLayout:(BOOL)flag
866 var lineFragment = _objectWithLocationInRange(_lineFragments, index);
870 if (effectiveGlyphRange)
872 effectiveGlyphRange.location = lineFragment._range.location;
873 effectiveGlyphRange.length = lineFragment._range.length;
876 return lineFragment._textContainer;
879 return [_textContainers lastObject];
882 - (
CPTextContainer)textContainerForGlyphAtIndex:(
unsigned)index effectiveRange:(CPRangePointer)effectiveGlyphRange
887 - (CPRange)characterRangeForGlyphRange:(CPRange)aRange actualGlyphRange:(CPRangePointer)actualRange
889 return _MakeRangeFromAbs([
self characterIndexForGlyphAtIndex:aRange.location],
890 [
self characterIndexForGlyphAtIndex:
CPMaxRange(aRange)]);
893 - (unsigned)characterIndexForGlyphAtIndex:(
unsigned)index
899 - (CPArray)rectArrayForCharacterRange:(CPRange)charRange
900 withinSelectedCharacterRange:(CPRange)selectedCharRange
902 rectCount:(CGRectPointer)rectCount
906 lineFragments = _objectsInRange(_lineFragments, selectedCharRange);
908 if (!lineFragments.length)
913 for (var i = 0; i < lineFragments.length; i++)
915 var fragment = lineFragments[i];
917 if (fragment._textContainer === container)
919 var frames = [fragment glyphFrames],
921 len = fragment._range.length;
923 for (var j = 0; j < len; j++)
927 var correctedRect = CGRectCreateCopy(frames[j]);
928 correctedRect.size.height -= frames[j]._descent;
929 correctedRect.origin.y -= frames[j]._descent;
931 rect = CGRectCreateCopy(correctedRect);
933 rect = CGRectUnion(rect, correctedRect);
935 if (_isNewlineCharacter([[_textStorage
string] characterAtIndex:MAX(0,
CPMaxRange(selectedCharRange) - 1)]))
937 rect.size.width = containerSize.width - rect.origin.x;
943 rectArray.push(rect);
947 var len = rectArray.length;
949 for (var i = 0; i < len - 1; i++)
951 if (FLOOR(CGRectGetMaxY(rectArray[i])) == FLOOR(CGRectGetMaxY(rectArray[i + 1])))
954 rectArray[i].size.width = containerSize.width - rectArray[i].origin.x;
975 _textStorage = [aCoder decodeObjectForKey:CPLayoutManagerTextStorageKey];
976 [_textStorage addLayoutManager:self];
984 [aCoder encodeObject:_textStorage forKey:CPLayoutManagerTextStorageKey];
992 - (unsigned)_indexOfObject:(
id)anObject sortedByFunction:(Function)aFunction context:(
id)aContext
994 var length=
self.length;
1007 while (first <= last)
1009 mid = FLOOR((first + last) / 2);
1010 c = aFunction(anObject,
self[mid], aContext);
1022 while (mid < length - 1 && aFunction(anObject,
self[mid + 1], aContext) ==
CPOrderedSame)
1029 var result = -first - 1;
1036 var _sortRange =
function(location, anObject)
1040 else if (
CPMaxRange(anObject._range) <= location)
1046 var _objectWithLocationInRange =
function(aList, aLocation)
1048 var index = [aList _indexOfObject:aLocation sortedByFunction:_sortRange context:nil];
1051 return aList[index];
1056 var _objectsInRange =
function(aList, aRange)
1058 var firstIndex = [aList _indexOfObject:aRange.location sortedByFunction:_sortRange context:nil],
1059 lastIndex = [aList _indexOfObject:CPMaxRange(aRange) sortedByFunction:_sortRange context:nil];
1065 lastIndex = aList.length - 1;
1067 return aList.slice(firstIndex, lastIndex + 1);
1070 @implementation _CPLineFragment :
CPObject 1072 CPArray _glyphsFrames;
1073 CPArray _glyphsOffsets;
1077 CGRect _fragmentRect;
1086 #pragma mark Init methods 1092 span = document.createElement(
"span");
1094 span.oncontextmenu = span.onmousedown = span.onselectstart = _oncontextmenuhandler;
1098 style.position =
"absolute";
1099 style.visibility =
"visible";
1100 style.padding =
"0px";
1101 style.margin =
"0px";
1102 style.whiteSpace =
"pre";
1103 style.backgroundColor =
"transparent";
1110 span.innerText = aString;
1112 span.textContent = aString;
1123 if (
self = [super
init])
1128 _fragmentRect = CGRectMakeZero();
1129 _usedRect = CGRectMakeZero();
1130 _location = CGPointMakeZero();
1132 _textContainer = aContainer;
1136 for (location = aRange.location; location <
CPMaxRange(aRange); location =
CPMaxRange(effectiveRange))
1142 var
string = [textStorage._string substringWithRange:effectiveRange],
1146 font = [attributes objectForKey:CPFontAttributeName];
1148 var color = [attributes objectForKey:CPForegroundColorAttributeName],
1149 elem = [
self createDOMElementWithText:string andFont:font andColor:color],
1150 run = {_range:
CPMakeRangeCopy(effectiveRange), color:color, font:font, elem:nil, string:
string};
1162 - (void)setAdvancements:(CPArray)someAdvancements
1164 var count = someAdvancements.length,
1165 origin = CGPointMake(_fragmentRect.origin.x + _location.x, _fragmentRect.origin.y),
1166 height = _usedRect.size.height;
1168 _glyphsFrames =
new Array(count);
1169 _glyphsOffsets =
new Array(count);
1171 for (var i = 0; i < count; i++)
1173 _glyphsFrames[i] = CGRectMake(origin.x, origin.y, someAdvancements[i].width, height);
1174 _glyphsFrames[i]._descent = someAdvancements[i].descent;
1175 _glyphsOffsets[i] = height - someAdvancements[i].height;
1176 origin.x += someAdvancements[i].
width;
1180 - (void)_adjustForHeight:(
double)height
1182 var count = _glyphsFrames.length;
1184 for (var i = 0; i < count; i++)
1185 _glyphsFrames[i].origin.y += (height - _fragmentRect.size.height);
1187 _fragmentRect.size.height = height;
1192 return [
super description] +
1199 - (void)drawUnderlineForGlyphRange:(CPRange)glyphRange
1200 underlineType:(
int)underlineVal
1201 baselineOffset:(
float)baselineOffset
1202 containerOrigin:(CGPoint)containerOrigin
1212 - (void)_deinvalidate
1217 - (void)_removeFromDOM
1219 var l = _runs.length;
1221 for (var i = 0; i < l; i++)
1223 if (_runs[i].elem && _runs[i].DOMactive)
1224 _textContainer._textView._DOMElement.removeChild(_runs[i].elem);
1226 _runs[i].elem = nil;
1227 _runs[i].DOMactive = NO;
1231 - (void)drawInContext:(CGContext)context atPoint:(CGPoint)aPoint forRange:(CPRange)aRange
1233 var runs = _objectsInRange(_runs, aRange),
1235 orig = CGPointMake(_fragmentRect.origin.x, _fragmentRect.origin.y);
1237 for (var i = 0; i < c; i++)
1243 run.elem=[self createDOMElementWithText:run.string andFont:run.font andColor:run.color];
1246 if (run.DOMactive && !run.DOMpatched)
1252 var loc = run._range.location - _runs[0]._range.location;
1253 orig.x = _glyphsFrames[loc].origin.x + aPoint.x;
1254 orig.y = _glyphsFrames[loc].origin.y + aPoint.y + _glyphsOffsets[loc];
1258 run.elem.style.left = (orig.x) +
"px";
1259 run.elem.style.top = (orig.y) +
"px";
1262 _textContainer._textView._DOMElement.appendChild(run.elem);
1264 run.DOMactive = YES;
1267 run.DOMpatched = NO;
1272 - (void)backgroundColorForGlyphAtIndex:(
unsigned)index
1274 var run = _objectWithLocationInRange(_runs, index);
1277 return run.backgroundColor;
1282 - (BOOL)isVisuallyIdenticalToFragment:(_CPLineFragment)newLineFragment
1284 var newFragmentRuns= newLineFragment._runs,
1285 oldFragmentRuns= _runs;
1287 if (!oldFragmentRuns || !newFragmentRuns || oldFragmentRuns.length !== newFragmentRuns.length)
1290 var l = oldFragmentRuns.length;
1292 for (var i = 0; i < l; i++)
1294 if (newFragmentRuns[i].
string !== oldFragmentRuns[i].
string)
1297 if (!_RectEqualToRectHorizontally(newLineFragment._fragmentRect, _fragmentRect))
1300 if (newFragmentRuns[i].color !== oldFragmentRuns[i].color || newFragmentRuns[i].font !== oldFragmentRuns[i].font)
1308 - (void)_relocateVerticallyByY:(
double)verticalOffset rangeOffset:(
unsigned)rangeOffset
1310 var l = _runs.length;
1312 _range.location += rangeOffset;
1314 for (var i = 0; i < l; i++)
1316 _runs[i]._range.location += rangeOffset;
1318 if (verticalOffset && _runs[i].elem)
1320 _runs[i].elem.top = (_runs[i].elem.top + verticalOffset) + 'px';
1321 _runs[i].DOMpatched = YES;
1325 if (!verticalOffset)
1328 _fragmentRect.origin.y += verticalOffset;
1329 _usedRect.origin.y += verticalOffset;
1331 var l = _glyphsFrames.length;
1333 for (var i = 0; i < l ; i++)
1335 _glyphsFrames[i].origin.y += verticalOffset;
1341 @implementation _CPTemporaryAttributes :
CPObject 1347 - (id)initWithRange:(CPRange)aRange attributes:(
CPDictionary)attributes
1349 if (
self = [super
init])
1351 _attributes = attributes;
1360 return [
super description] +
1367 @implementation CPLayoutManager (CPSynthesizedAccessors)
1372 - (void)setLineFragmentFactory:(Class)aValue
1374 _lineFragmentFactory = aValue;
1382 return _textContainers;
1390 return _textStorage;
1398 _textStorage = aValue;
1414 _typesetter = aValue;
function CPUnionRange(lhsRange, rhsRange)
CPFont systemFontOfSize:(CGSize aSize)
CPTextContainer textContainerForGlyphAtIndex:effectiveRange:withoutAdditionalLayout:(unsigned index, [effectiveRange] CPRangePointer effectiveGlyphRange, [withoutAdditionalLayout] BOOL flag)
CPResponder firstResponder()
CPJavaScriptInnerTextFeature
CPDictionary attributesAtIndex:effectiveRange:(CPUInteger anIndex, [effectiveRange] CPRangePointer aRange)
A mutable key-value pair collection.
function CPStringFromRange(aRange)
CPTextView firstTextView()
function CPMaxRange(aRange)
An immutable string (collection of characters).
unsigned glyphIndexForPoint:inTextContainer:fractionOfDistanceThroughGlyph:(CGPoint point, [inTextContainer] CPTextContainer container, [fractionOfDistanceThroughGlyph] FloatArray partialFraction)
CPJavaScriptTextContentFeature
if(CPFeatureIsCompatible(CPHTMLCanvasFeature))
function CPFeatureIsCompatible(aFeature)
void invalidateDisplayForGlyphRange:(CPRange range)
var CPLayoutManagerTextStorageKey
function CPIntersectionRange(lhsRange, rhsRange)
function CPMakeRangeCopy(aRange)
Defines methods for use when archiving & restoring (enc/decoding).
id sharedSystemTypesetter()
function CPLocationInRange(aLocation, aRange)
void invalidateLayoutForCharacterRange:isSoft:actualCharacterRange:(CPRange aRange, [isSoft] BOOL flag, [actualCharacterRange] CPRangePointer actualCharRange)
CompletionHandlerAgent prototype invalidate
void setLayoutManager:(CPLayoutManager aValue)
CPRange function CPMakeRange(location, length)
FrameUpdater prototype description