Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(118)

Side by Side Diff: Source/core/editing/spellcheck/SpellChecker.cpp

Issue 1329253002: WIP: prefer using EphemeralRange for SpellChecker. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: introduce Range::dispose() Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 return; 480 return;
481 481
482 // If we're not in an editable node, bail. 482 // If we're not in an editable node, bail.
483 Node* editableNode = spellingRange.startPosition().computeContainerNode(); 483 Node* editableNode = spellingRange.startPosition().computeContainerNode();
484 if (!editableNode || !editableNode->hasEditableStyle()) 484 if (!editableNode || !editableNode->hasEditableStyle())
485 return; 485 return;
486 486
487 if (!isSpellCheckingEnabledFor(editableNode)) 487 if (!isSpellCheckingEnabledFor(editableNode))
488 return; 488 return;
489 489
490 RefPtrWillBeRawPtr<Range> rangeToCheck = createRange(shouldMarkGrammar ? gra mmarRange : spellingRange); 490 TextCheckingParagraph fullParagraphToCheck(shouldMarkGrammar ? grammarRange : spellingRange);
491 TextCheckingParagraph fullParagraphToCheck(rangeToCheck);
492 491
493 bool asynchronous = frame().settings() && frame().settings()->asynchronousSp ellCheckingEnabled(); 492 bool asynchronous = frame().settings() && frame().settings()->asynchronousSp ellCheckingEnabled();
494 chunkAndMarkAllMisspellingsAndBadGrammar(textCheckingOptions, fullParagraphT oCheck, asynchronous); 493 chunkAndMarkAllMisspellingsAndBadGrammar(textCheckingOptions, fullParagraphT oCheck, asynchronous);
495 } 494 }
496 495
497 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(Node* node) 496 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(Node* node)
498 { 497 {
499 TRACE_EVENT0("blink", "SpellChecker::chunkAndMarkAllMisspellingsAndBadGramma r"); 498 TRACE_EVENT0("blink", "SpellChecker::chunkAndMarkAllMisspellingsAndBadGramma r");
500 if (!node) 499 if (!node)
501 return; 500 return;
502 RefPtrWillBeRawPtr<Range> rangeToCheck = Range::create(*frame().document(), firstPositionInNode(node), lastPositionInNode(node)); 501 RefPtrWillBeRawPtr<Range> rangeToCheck = Range::create(*frame().document(), firstPositionInNode(node), lastPositionInNode(node));
503 TextCheckingParagraph textToCheck(rangeToCheck, rangeToCheck); 502 TextCheckingParagraph textToCheck(rangeToCheck, rangeToCheck);
504 bool asynchronous = true; 503 bool asynchronous = true;
505 chunkAndMarkAllMisspellingsAndBadGrammar(resolveTextCheckingTypeMask(TextChe ckingTypeSpelling | TextCheckingTypeGrammar), textToCheck, asynchronous); 504 chunkAndMarkAllMisspellingsAndBadGrammar(resolveTextCheckingTypeMask(TextChe ckingTypeSpelling | TextCheckingTypeGrammar), textToCheck, asynchronous);
506 } 505 }
507 506
508 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(TextCheckingTypeMask textCheckingOptions, const TextCheckingParagraph& fullParagraphToCheck, bool as ynchronous) 507 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(TextCheckingTypeMask textCheckingOptions, const TextCheckingParagraph& fullParagraphToCheck, bool as ynchronous)
509 { 508 {
510 if (fullParagraphToCheck.isRangeEmpty() || fullParagraphToCheck.isEmpty()) 509 if (fullParagraphToCheck.isRangeEmpty() || fullParagraphToCheck.isEmpty())
511 return; 510 return;
512 511
513 // Since the text may be quite big chunk it up and adjust to the sentence bo undary. 512 // Since the text may be quite big chunk it up and adjust to the sentence bo undary.
514 const int kChunkSize = 16 * 1024; 513 const int kChunkSize = 16 * 1024;
515 int start = fullParagraphToCheck.checkingStart(); 514 int start = fullParagraphToCheck.checkingStart();
516 int end = fullParagraphToCheck.checkingEnd(); 515 int end = fullParagraphToCheck.checkingEnd();
517 start = std::min(start, end); 516 start = std::min(start, end);
518 end = std::max(start, end); 517 end = std::max(start, end);
519 const int kNumChunksToCheck = asynchronous ? (end - start + kChunkSize - 1) / (kChunkSize) : 1; 518 const int kNumChunksToCheck = asynchronous ? (end - start + kChunkSize - 1) / (kChunkSize) : 1;
520 int currentChunkStart = start; 519 int currentChunkStart = start;
521 RefPtrWillBeRawPtr<Range> checkRange = fullParagraphToCheck.checkingRange(); 520 EphemeralRange checkRange = fullParagraphToCheck.checkingRange();
yosin_UTC9 2015/09/10 01:58:39 nit: |const EphemeralRange|.
522 if (kNumChunksToCheck == 1 && asynchronous) { 521 if (kNumChunksToCheck == 1 && asynchronous) {
523 markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, checkRange .get(), checkRange.get(), asynchronous, 0); 522 markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, checkRange , checkRange, asynchronous, 0);
524 return; 523 return;
525 } 524 }
526 525
527 for (int iter = 0; iter < kNumChunksToCheck; ++iter) { 526 for (int iter = 0; iter < kNumChunksToCheck; ++iter) {
528 checkRange = fullParagraphToCheck.subrange(currentChunkStart, kChunkSize ); 527 checkRange = fullParagraphToCheck.subrange(currentChunkStart, kChunkSize );
yosin_UTC9 2015/09/10 01:58:39 nit: Let's use new variable name. We don't want to
529 expandRangeToSentenceBoundary(*checkRange); 528 checkRange = expandRangeToSentenceBoundary(checkRange);
530 529
531 int checkingLength = 0; 530 int checkingLength = 0;
532 markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, checkRange .get(), checkRange.get(), asynchronous, iter, &checkingLength); 531 markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, checkRange , checkRange, asynchronous, iter, &checkingLength);
533 currentChunkStart += checkingLength; 532 currentChunkStart += checkingLength;
534 } 533 }
535 } 534 }
536 535
537 void SpellChecker::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask textCheckingOptions, Range* checkRange, Range* paragraphRange, bool asynchronou s, int requestNumber, int* checkingLength) 536 void SpellChecker::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask textCheckingOptions, const EphemeralRange& checkRange, const EphemeralRange& pa ragraphRange, bool asynchronous, int requestNumber, int* checkingLength)
538 { 537 {
539 TextCheckingParagraph sentenceToCheck(checkRange, paragraphRange); 538 TextCheckingParagraph sentenceToCheck(checkRange, paragraphRange);
540 if (checkingLength) 539 if (checkingLength)
541 *checkingLength = sentenceToCheck.checkingLength(); 540 *checkingLength = sentenceToCheck.checkingLength();
542 541
543 RefPtrWillBeRawPtr<SpellCheckRequest> request = SpellCheckRequest::create(re solveTextCheckingTypeMask(textCheckingOptions), TextCheckingProcessBatch, checkR ange, paragraphRange, requestNumber); 542 RefPtrWillBeRawPtr<SpellCheckRequest> request = SpellCheckRequest::create(re solveTextCheckingTypeMask(textCheckingOptions), TextCheckingProcessBatch, create Range(checkRange), createRange(paragraphRange), requestNumber);
544 if (!request) 543 if (!request)
545 return; 544 return;
546 545
547 if (asynchronous) { 546 if (asynchronous) {
548 m_spellCheckRequester->requestCheckingFor(request); 547 m_spellCheckRequester->requestCheckingFor(request);
549 } else { 548 } else {
550 Vector<TextCheckingResult> results; 549 Vector<TextCheckingResult> results;
551 checkTextOfParagraph(textChecker(), sentenceToCheck.text(), resolveTextC heckingTypeMask(textCheckingOptions), results); 550 checkTextOfParagraph(textChecker(), sentenceToCheck.text(), resolveTextC heckingTypeMask(textCheckingOptions), results);
552 markAndReplaceFor(request, results); 551 markAndReplaceFor(request, results);
553 } 552 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 int resultLength = result->length; 590 int resultLength = result->length;
592 bool resultEndsAtAmbiguousBoundary = ambiguousBoundaryOffset >= 0 && res ultLocation + resultLength == ambiguousBoundaryOffset; 591 bool resultEndsAtAmbiguousBoundary = ambiguousBoundaryOffset >= 0 && res ultLocation + resultLength == ambiguousBoundaryOffset;
593 592
594 // Only mark misspelling if: 593 // Only mark misspelling if:
595 // 1. Current text checking isn't done for autocorrection, in which case shouldMarkSpelling is false. 594 // 1. Current text checking isn't done for autocorrection, in which case shouldMarkSpelling is false.
596 // 2. Result falls within spellingRange. 595 // 2. Result falls within spellingRange.
597 // 3. The word in question doesn't end at an ambiguous boundary. For ins tance, we would not mark 596 // 3. The word in question doesn't end at an ambiguous boundary. For ins tance, we would not mark
598 // "wouldn'" as misspelled right after apostrophe is typed. 597 // "wouldn'" as misspelled right after apostrophe is typed.
599 if (shouldMarkSpelling && result->decoration == TextDecorationTypeSpelli ng && resultLocation >= paragraph.checkingStart() && resultLocation + resultLeng th <= spellingRangeEndOffset && !resultEndsAtAmbiguousBoundary) { 598 if (shouldMarkSpelling && result->decoration == TextDecorationTypeSpelli ng && resultLocation >= paragraph.checkingStart() && resultLocation + resultLeng th <= spellingRangeEndOffset && !resultEndsAtAmbiguousBoundary) {
600 ASSERT(resultLength > 0 && resultLocation >= 0); 599 ASSERT(resultLength > 0 && resultLocation >= 0);
601 const EphemeralRange misspellingRange = calculateCharacterSubrange(E phemeralRange(paragraph.paragraphRange().get()), resultLocation, resultLength); 600 const EphemeralRange misspellingRange = calculateCharacterSubrange(p aragraph.paragraphRange(), resultLocation, resultLength);
602 frame().document()->markers().addMarker(misspellingRange.startPositi on(), misspellingRange.endPosition(), DocumentMarker::Spelling, result->replacem ent, result->hash); 601 frame().document()->markers().addMarker(misspellingRange.startPositi on(), misspellingRange.endPosition(), DocumentMarker::Spelling, result->replacem ent, result->hash);
603 } else if (shouldMarkGrammar && result->decoration == TextDecorationType Grammar && paragraph.checkingRangeCovers(resultLocation, resultLength)) { 602 } else if (shouldMarkGrammar && result->decoration == TextDecorationType Grammar && paragraph.checkingRangeCovers(resultLocation, resultLength)) {
604 ASSERT(resultLength > 0 && resultLocation >= 0); 603 ASSERT(resultLength > 0 && resultLocation >= 0);
605 for (unsigned j = 0; j < result->details.size(); j++) { 604 for (unsigned j = 0; j < result->details.size(); j++) {
606 const GrammarDetail* detail = &result->details[j]; 605 const GrammarDetail* detail = &result->details[j];
607 ASSERT(detail->length > 0 && detail->location >= 0); 606 ASSERT(detail->length > 0 && detail->location >= 0);
608 if (paragraph.checkingRangeCovers(resultLocation + detail->locat ion, detail->length)) { 607 if (paragraph.checkingRangeCovers(resultLocation + detail->locat ion, detail->length)) {
609 const EphemeralRange badGrammarRange = calculateCharacterSub range(EphemeralRange(paragraph.paragraphRange().get()), resultLocation + detail- >location, detail->length); 608 const EphemeralRange badGrammarRange = calculateCharacterSub range(paragraph.paragraphRange(), resultLocation + detail->location, detail->len gth);
610 frame().document()->markers().addMarker(badGrammarRange.star tPosition(), badGrammarRange.endPosition(), DocumentMarker::Grammar, detail->use rDescription, result->hash); 609 frame().document()->markers().addMarker(badGrammarRange.star tPosition(), badGrammarRange.endPosition(), DocumentMarker::Grammar, detail->use rDescription, result->hash);
611 } 610 }
612 } 611 }
613 } else if (result->decoration == TextDecorationTypeInvisibleSpellcheck & & resultLocation >= paragraph.checkingStart() && resultLocation + resultLength < = spellingRangeEndOffset) { 612 } else if (result->decoration == TextDecorationTypeInvisibleSpellcheck & & resultLocation >= paragraph.checkingStart() && resultLocation + resultLength < = spellingRangeEndOffset) {
614 ASSERT(resultLength > 0 && resultLocation >= 0); 613 ASSERT(resultLength > 0 && resultLocation >= 0);
615 const EphemeralRange invisibleSpellcheckRange = calculateCharacterSu brange(EphemeralRange(paragraph.paragraphRange().get()), resultLocation, resultL ength); 614 const EphemeralRange invisibleSpellcheckRange = calculateCharacterSu brange(paragraph.paragraphRange(), resultLocation, resultLength);
616 frame().document()->markers().addMarker(invisibleSpellcheckRange.sta rtPosition(), invisibleSpellcheckRange.endPosition(), DocumentMarker::InvisibleS pellcheck, result->replacement, result->hash); 615 frame().document()->markers().addMarker(invisibleSpellcheckRange.sta rtPosition(), invisibleSpellcheckRange.endPosition(), DocumentMarker::InvisibleS pellcheck, result->replacement, result->hash);
617 } 616 }
618 } 617 }
619 618
620 if (selectionChanged) { 619 if (selectionChanged) {
621 TextCheckingParagraph extendedParagraph(paragraph); 620 TextCheckingParagraph extendedParagraph(paragraph);
622 // Restore the caret position if we have made any replacements 621 // Restore the caret position if we have made any replacements
623 extendedParagraph.expandRangeToNextEnd(); 622 extendedParagraph.expandRangeToNextEnd();
624 if (restoreSelectionAfterChange && selectionOffset >= 0 && selectionOffs et <= extendedParagraph.rangeLength()) { 623 if (restoreSelectionAfterChange && selectionOffset >= 0 && selectionOffs et <= extendedParagraph.rangeLength()) {
625 RefPtrWillBeRawPtr<Range> selectionRange = extendedParagraph.subrang e(0, selectionOffset); 624 EphemeralRange selectionRange = extendedParagraph.subrange(0, select ionOffset);
yosin_UTC9 2015/09/10 01:58:39 nit: |const EphemeralRange|
626 frame().selection().moveTo(selectionRange->endPosition(), TextAffini ty::Downstream); 625 frame().selection().moveTo(selectionRange.endPosition(), TextAffinit y::Downstream);
627 if (adjustSelectionForParagraphBoundaries) 626 if (adjustSelectionForParagraphBoundaries)
628 frame().selection().modify(FrameSelection::AlterationMove, Direc tionForward, CharacterGranularity); 627 frame().selection().modify(FrameSelection::AlterationMove, Direc tionForward, CharacterGranularity);
629 } else { 628 } else {
630 // If this fails for any reason, the fallback is to go one position beyond the last replacement 629 // If this fails for any reason, the fallback is to go one position beyond the last replacement
631 frame().selection().moveTo(frame().selection().selection().visibleEn d()); 630 frame().selection().moveTo(frame().selection().selection().visibleEn d());
632 frame().selection().modify(FrameSelection::AlterationMove, Direction Forward, CharacterGranularity); 631 frame().selection().modify(FrameSelection::AlterationMove, Direction Forward, CharacterGranularity);
633 } 632 }
634 } 633 }
635 } 634 }
636 635
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 m_spellCheckRequester->requestCheckingFor(SpellCheckRequest::create(TextChec kingTypeSpelling | TextCheckingTypeGrammar, TextCheckingProcessBatch, rangeToChe ck, rangeToCheck)); 937 m_spellCheckRequester->requestCheckingFor(SpellCheckRequest::create(TextChec kingTypeSpelling | TextCheckingTypeGrammar, TextCheckingProcessBatch, rangeToChe ck, rangeToCheck));
939 } 938 }
940 939
941 DEFINE_TRACE(SpellChecker) 940 DEFINE_TRACE(SpellChecker)
942 { 941 {
943 visitor->trace(m_frame); 942 visitor->trace(m_frame);
944 visitor->trace(m_spellCheckRequester); 943 visitor->trace(m_spellCheckRequester);
945 } 944 }
946 945
947 } // namespace blink 946 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698