{"action":"created","comment":{"url":"https://api.github.com/repos/Microsoft/WinObjC/pulls/comments/90737304","pull_request_review_id":11258361,"id":90737304,"diff_hunk":"@@ -97,97 +108,130 @@ bool _CloneDWriteGlyphRun(_In_ DWRITE_GLYPH_RUN const* src, _Out_ DWRITE_GLYPH_R\n }\n \n /**\n+ * Private helper that applies a CTParagraphStyleRef to an IDWriteTextFormat\n+ */\n+static inline HRESULT __DWriteTextFormatApplyParagraphStyle(const ComPtr<IDWriteTextFormat>& textFormat, CTParagraphStyleRef settings) {\n+    CTTextAlignment alignment = kCTNaturalTextAlignment;\n+    if (CTParagraphStyleGetValueForSpecifier(settings, kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment), &alignment)) {\n+        RETURN_IF_FAILED(textFormat->SetTextAlignment(__CTAlignmentToDWrite(alignment)));\n+    }\n+\n+    CTWritingDirection direction;\n+    if (CTParagraphStyleGetValueForSpecifier(settings, kCTParagraphStyleSpecifierBaseWritingDirection, sizeof(direction), &direction)) {\n+        DWRITE_READING_DIRECTION dwriteDirection = DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;\n+        if (direction == kCTWritingDirectionRightToLeft) {\n+            dwriteDirection = DWRITE_READING_DIRECTION_RIGHT_TO_LEFT;\n+\n+            // DWrite alignment is based upon reading direction whereas CoreText alignment is constant\n+            // so we have to flip the writing direction\n+            if (alignment == kCTRightTextAlignment || alignment == kCTNaturalTextAlignment) {\n+                RETURN_IF_FAILED(textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING));\n+            } else if (alignment == kCTLeftTextAlignment) {\n+                RETURN_IF_FAILED(textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING));\n+            }\n+        }\n+\n+        RETURN_IF_FAILED(textFormat->SetReadingDirection(dwriteDirection));\n+    }\n+\n+    CTLineBreakMode lineBreakMode;\n+    if (CTParagraphStyleGetValueForSpecifier(settings, kCTParagraphStyleSpecifierLineBreakMode, sizeof(lineBreakMode), &lineBreakMode)) {\n+        RETURN_IF_FAILED(textFormat->SetWordWrapping(__CTLineBreakModeToDWrite(lineBreakMode)));\n+    }\n+\n+    return S_OK;\n+}\n+\n+/**\n+ * Private helper that applies a CTFontRef to an IDWriteTextLayout within the specified range.\n+ */\n+static inline HRESULT __DWriteTextLayoutApplyFont(const ComPtr<IDWriteTextLayout>& textLayout, CTFontRef font, DWRITE_TEXT_RANGE range) {\n+    std::shared_ptr<_DWriteFontProperties> properties = _DWriteGetFontPropertiesFromName(CTFontCopyName(font, kCTFontFullNameKey));\n+    RETURN_IF_FAILED(textLayout->SetFontWeight(properties->weight, range));\n+    RETURN_IF_FAILED(textLayout->SetFontStretch(properties->stretch, range));\n+    RETURN_IF_FAILED(textLayout->SetFontStyle(properties->style, range));\n+\n+    RETURN_IF_FAILED(textLayout->SetFontSize(CTFontGetSize(font), range));\n+    RETURN_IF_FAILED(\n+        textLayout->SetFontFamilyName(reinterpret_cast<wchar_t*>(Strings::VectorFromCFString(properties->familyName.get()).data()), range));\n+\n+    return S_OK;\n+}\n+\n+/**\n+ * Private helper that applies extra kerning to an IDWriteTextLayout within the specified range.\n+ */\n+static inline HRESULT __DWriteTextLayoutApplyExtraKerning(const ComPtr<IDWriteTextLayout>& textLayout,\n+                                                          const ComPtr<IDWriteTypography>& typography,\n+                                                          CFNumberRef extraKerningRef,\n+                                                          DWRITE_TEXT_RANGE range) {\n+    ComPtr<IDWriteTextLayout1> textLayout1;\n+    RETURN_IF_FAILED(textLayout.As(&textLayout1));\n+\n+    CGFloat extraKerning;\n+    CFNumberGetValue(extraKerningRef, kCFNumberFloatType, &extraKerning);\n+\n+    CGFloat leadingSpacing, trailingSpacing, minimumAdvanceWidth;\n+    RETURN_IF_FAILED(textLayout1->GetCharacterSpacing(range.startPosition, &leadingSpacing, &trailingSpacing, &minimumAdvanceWidth));\n+    RETURN_IF_FAILED(textLayout1->SetCharacterSpacing(leadingSpacing, trailingSpacing + extraKerning, minimumAdvanceWidth, range));\n+\n+    // Setting kern disables default kerning\n+    RETURN_IF_FAILED(typography->AddFontFeature({ DWRITE_FONT_FEATURE_TAG_KERNING, 0 }));\n+\n+    return S_OK;\n+}\n+\n+/**\n  * Helper method to create a IDWriteTextFormat object given _CTTypesetter object and string range.\n  *\n  * @parameter ts _CTTypesetter object.\n  * @parameter range string range to consider for rendering.\n+ * @parameter outTextFormat outpointer for creating the text format\n  *\n- * @return the created IDWriteTextFormat object.\n+ * @return whether the creation was successful\n  */\n-static ComPtr<IDWriteTextFormat> __CreateDWriteTextFormat(CFAttributedStringRef string, CFRange range) {\n-    // TODO::\n-    // Note here we only look at attribute value at first index of the specified range as we can get a default faont size to use here.\n-    // Per string range attribute handling will be done in _CreateDWriteTextLayout.\n-\n-    NSDictionary* attribs = [static_cast<NSAttributedString*>(string) attributesAtIndex:range.location effectiveRange:NULL];\n-\n-    CGFloat fontSize = kCTFontSystemFontSize;\n-    CTFontRef font = static_cast<CTFontRef>([attribs objectForKey:static_cast<NSString*>(kCTFontAttributeName)]);\n-    std::vector<wchar_t> familyName;\n+static HRESULT __DWriteTextFormatCreate(CFAttributedStringRef string, CFRange range, _Out_ IDWriteTextFormat** outTextFormat) {\n+    RETURN_HR_IF(E_INVALIDARG, !outTextFormat);\n \n     std::shared_ptr<_DWriteFontProperties> properties;\n+    CGFloat fontSize;\n+\n+    // TODO::\n+    // Note here we only look at attribute value at first index of the specified range as we can get a default font size to use here.\n+    // Per string range attribute handling will be done in _CreateDWriteTextLayout.\n+    CTFontRef font = static_cast<CTFontRef>(CFAttributedStringGetAttribute(string, range.location, kCTFontAttributeName, nullptr));\n \n     if (font) {\n+        woc::unique_cf<CFStringRef> fontFullName(CTFontCopyName(font, kCTFontFullNameKey));\n+        properties = _DWriteGetFontPropertiesFromName(fontFullName.get());\n         fontSize = CTFontGetSize(font);\n-        CFStringRef fontFullName = CTFontCopyName(font, kCTFontFullNameKey);\n-        CFAutorelease(fontFullName);\n-        properties = _DWriteGetFontPropertiesFromName(fontFullName);\n     } else {\n         properties = std::make_shared<_DWriteFontProperties>();\n+        fontSize = kCTFontSystemFontSize;\n     }\n \n-    familyName.resize(CFStringGetLength(properties->familyName.get()) + 1, 0);\n-    CFStringGetCharacters(properties->familyName.get(), CFRangeMake(0, familyName.size()), reinterpret_cast<UniChar*>(familyName.data()));\n-\n+    ComPtr<IDWriteFactory> dwriteFactory;\n+    RETURN_IF_FAILED(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &dwriteFactory));\n     ComPtr<IDWriteTextFormat> textFormat;\n-    RETURN_NULL_IF_FAILED(\n-        _DWriteCreateTextFormat(familyName.data(), properties->weight, properties->style, properties->stretch, fontSize, &textFormat));\n-\n+    RETURN_IF_FAILED(\n+        dwriteFactory->CreateTextFormat(reinterpret_cast<wchar_t*>(Strings::VectorFromCFString(properties->familyName.get()).data()),\n+                                        nullptr,\n+                                        properties->weight,\n+                                        properties->style,\n+                                        properties->stretch,\n+                                        fontSize,\n+                                        _GetUserDefaultLocaleName().data(),\n+                                        &textFormat));\n+\n+    // Apply paragraph style if one exists in the attributed string\n     CTParagraphStyleRef settings =\n-        static_cast<CTParagraphStyleRef>([attribs valueForKey:static_cast<NSString*>(kCTParagraphStyleAttributeName)]);\n+        static_cast<CTParagraphStyleRef>(CFAttributedStringGetAttribute(string, range.location, kCTParagraphStyleAttributeName, nullptr));\n     if (settings) {\n-        CTTextAlignment alignment = kCTNaturalTextAlignment;\n-        if (CTParagraphStyleGetValueForSpecifier(settings, kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment), &alignment)) {\n-            DWRITE_TEXT_ALIGNMENT dwriteAlignment = __CoreTextAlignmentToDwrite(alignment);\n-            RETURN_NULL_IF_FAILED(textFormat->SetTextAlignment(dwriteAlignment));\n-        }\n-\n-        CTWritingDirection direction;\n-        if (CTParagraphStyleGetValueForSpecifier(settings, kCTParagraphStyleSpecifierBaseWritingDirection, sizeof(direction), &direction)) {\n-            DWRITE_READING_DIRECTION dwriteDirection = DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;\n-            if (direction == kCTWritingDirectionRightToLeft) {\n-                dwriteDirection = DWRITE_READING_DIRECTION_RIGHT_TO_LEFT;\n-\n-                // DWrite alignment is based upon reading direction whereas CoreText alignment is constant\n-                // so we have to flip the writing direction\n-                if (alignment == kCTRightTextAlignment || alignment == kCTNaturalTextAlignment) {\n-                    RETURN_NULL_IF_FAILED(textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING));\n-                } else if (alignment == kCTLeftTextAlignment) {\n-                    RETURN_NULL_IF_FAILED(textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING));\n-                }\n-            }\n-\n-            RETURN_NULL_IF_FAILED(textFormat->SetReadingDirection(dwriteDirection));\n-        }\n-\n-        CTLineBreakMode lineBreakMode;\n-        if (CTParagraphStyleGetValueForSpecifier(settings,\n-                                                 kCTParagraphStyleSpecifierLineBreakMode,\n-                                                 sizeof(lineBreakMode),\n-                                                 &lineBreakMode)) {\n-            DWRITE_WORD_WRAPPING wrapping;\n-            switch (lineBreakMode) {\n-                // TODO 1121:: DWrite does not support line breaking by truncation, so just use clipping for now\n-                case kCTLineBreakByTruncatingHead:\n-                case kCTLineBreakByTruncatingTail:\n-                case kCTLineBreakByTruncatingMiddle:\n-                case kCTLineBreakByClipping:\n-                    wrapping = DWRITE_WORD_WRAPPING_NO_WRAP;\n-                    break;\n-                case kCTLineBreakByCharWrapping:\n-                    wrapping = DWRITE_WORD_WRAPPING_CHARACTER;\n-                    break;\n-                case kCTLineBreakByWordWrapping:\n-                default:\n-                    wrapping = DWRITE_WORD_WRAPPING_WRAP;\n-                    break;\n-            }\n-\n-            THROW_IF_FAILED(textFormat->SetWordWrapping(wrapping));\n-        }\n+        RETURN_IF_FAILED(__DWriteTextFormatApplyParagraphStyle(textFormat, settings));\n     }\n \n-    return textFormat;\n+    *outTextFormat = textFormat.Detach();","path":"Frameworks/CoreText/DWriteWrapper_CoreText.mm","position":257,"original_position":257,"commit_id":"4fad65482028cad182459816aceab43dcd4ab981","original_commit_id":"4fad65482028cad182459816aceab43dcd4ab981","user":{"login":"msft-Jeyaram","id":18413092,"avatar_url":"https://avatars.githubusercontent.com/u/18413092?v=3","gravatar_id":"","url":"https://api.github.com/users/msft-Jeyaram","html_url":"https://github.com/msft-Jeyaram","followers_url":"https://api.github.com/users/msft-Jeyaram/followers","following_url":"https://api.github.com/users/msft-Jeyaram/following{/other_user}","gists_url":"https://api.github.com/users/msft-Jeyaram/gists{/gist_id}","starred_url":"https://api.github.com/users/msft-Jeyaram/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/msft-Jeyaram/subscriptions","organizations_url":"https://api.github.com/users/msft-Jeyaram/orgs","repos_url":"https://api.github.com/users/msft-Jeyaram/repos","events_url":"https://api.github.com/users/msft-Jeyaram/events{/privacy}","received_events_url":"https://api.github.com/users/msft-Jeyaram/received_events","type":"User","site_admin":false},"body":">Detach [](start = 32, length = 6)\r\n\r\nuse CopyTo(...)","created_at":"2016-12-02T23:20:32Z","updated_at":"2016-12-02T23:20:32Z","html_url":"https://github.com/Microsoft/WinObjC/pull/1504#discussion_r90737304","pull_request_url":"https://api.github.com/repos/Microsoft/WinObjC/pulls/1504","_links":{"self":{"href":"https://api.github.com/repos/Microsoft/WinObjC/pulls/comments/90737304"},"html":{"href":"https://github.com/Microsoft/WinObjC/pull/1504#discussion_r90737304"},"pull_request":{"href":"https://api.github.com/repos/Microsoft/WinObjC/pulls/1504"}}},"pull_request":{"url":"https://api.github.com/repos/Microsoft/WinObjC/pulls/1504","id":96368705,"html_url":"https://github.com/Microsoft/WinObjC/pull/1504","diff_url":"https://github.com/Microsoft/WinObjC/pull/1504.diff","patch_url":"https://github.com/Microsoft/WinObjC/pull/1504.patch","issue_url":"https://api.github.com/repos/Microsoft/WinObjC/issues/1504","number":1504,"state":"open","locked":false,"title":"Refactor some DWriteWrapper code","user":{"login":"ms-jihua","id":16024095,"avatar_url":"https://avatars.githubusercontent.com/u/16024095?v=3","gravatar_id":"","url":"https://api.github.com/users/ms-jihua","html_url":"https://github.com/ms-jihua","followers_url":"https://api.github.com/users/ms-jihua/followers","following_url":"https://api.github.com/users/ms-jihua/following{/other_user}","gists_url":"https://api.github.com/users/ms-jihua/gists{/gist_id}","starred_url":"https://api.github.com/users/ms-jihua/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ms-jihua/subscriptions","organizations_url":"https://api.github.com/users/ms-jihua/orgs","repos_url":"https://api.github.com/users/ms-jihua/repos","events_url":"https://api.github.com/users/ms-jihua/events{/privacy}","received_events_url":"https://api.github.com/users/ms-jihua/received_events","type":"User","site_admin":false},"body":"- Split DWriteWrapper, DWriteWrapper_CoreText among more files\r\n  - DWriteFontBinaryDataLoader is now in its own .h + .mm along with BinaryDataStream\r\n  - DWriteFontCollectionLoader is now in its own .h + .mm along with FileEnumerator\r\n    - Renamed to DWriteFontBinaryDataCollectionLoader to get the name farther from the interface name (IDWriteFontCollectionLoader)\r\n  - Implementation for _DWriteFontCreatePathForGlyph(), and the __CGPathGeometrySink class,\r\n    which was only used in this function, are now in a separate .mm file\r\n  - Implementation for DWriteFont_CoreText functions relating to CTFont, CTFontDescriptor are now in a separate .mm file\r\n  - Refactored _userFontCollection, s_userFontPropertiesMap, systemFontPropertiesMap to be behind an abstraction layer,\r\n    DWriteFontCollectionHelper, which wraps around either a user or system IDWriteFontCollection and provides\r\n    font name -> other name/family name, properties mappings.\r\n    - This is in its own .h + .mm file\r\n    - As a result, many _DWrite functions now reduce cleanly to\r\n      __GetSystemFontCollectionHelper()->Foo(), lock, __GetUserFontCollectionHelper()->Foo()\r\n\r\n- Refactored __CreateDWriteTextFormat(), __CreateDWriteTextLayout()\r\n  - Removed export of _DWriteCreateTextFormat(), this is now done directly in DWriteWrapper_CoreText.mm\r\n  - Now return HRESULT instead of ComPtr, now create through out-pointers, changed naming convention\r\n    - As a result, __CreateDWriteTextFormat no longer always returns a nullptr if an error occurs -\r\n      this should not impact anything, as this was an internal function, and return values were never checked for nullptr anyway\r\n  - Use CFAttributedStringGetAttribute directly instead of copying to a dictionary first,\r\n    this should save some time on redundant copies/copies of unused attributes\r\n  - Parts of these functions were moved into separate inline functions for easier reading\r\n\r\n- Reversed order of i, j in _DWriteGetFrame(), such that i is on the outside and j on the inside\r\n  - Replaced the inner two while loops, with a single for loop\r\n\r\n- Exported _GetDefaultUserLocaleName()\r\n- Broke parts of _DWriteCreateFontFaceWithFontDescriptor() into separate functions for easier readability (less nesting)\r\n- Moved CustomDWriteTextRenderer member functions bodies to inside the class body\r\n- _CFStringCreateUppercaseCopy now uses a nullptr CFLocale (faster, font names are not localized anyway)\r\n  - Removed a redundant call to CFStringCreateUppercaseCopy() in the initialization of a font property map\r\n\r\n- Changed most remaining instances where CFAutorelease was used to use woc::unique_cf instead\r\n- Standardized naming convention of functions that translate a DWrite constant to CT/CG, or vice-versa\r\n- Changed members of most C++ classes to use the m_ naming convention\r\n- Standardized most file-private functions to be static\r\n- Standardized most instances of loops that call functions that return HRESULTs to call continue on failure\r\n- Changed CTTypesetterCreateLineWithOffset() to log and return null instead of throw\r\n- Added a bunch of SAL annotations\r\n- Added a string helper for copying a CFString to a vector, this was a pattern that occurred multiple times\r\n- Added comments in various places\r\n\r\nFixes #1212","created_at":"2016-12-02T23:04:37Z","updated_at":"2016-12-02T23:20:32Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d2c3ae84fc58112f8862d19e82c6b0463073c856","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/Microsoft/WinObjC/pulls/1504/commits","review_comments_url":"https://api.github.com/repos/Microsoft/WinObjC/pulls/1504/comments","review_comment_url":"https://api.github.com/repos/Microsoft/WinObjC/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Microsoft/WinObjC/issues/1504/comments","statuses_url":"https://api.github.com/repos/Microsoft/WinObjC/statuses/4fad65482028cad182459816aceab43dcd4ab981","head":{"label":"ms-jihua:ct_refactor4","ref":"ct_refactor4","sha":"4fad65482028cad182459816aceab43dcd4ab981","user":{"login":"ms-jihua","id":16024095,"avatar_url":"https://avatars.githubusercontent.com/u/16024095?v=3","gravatar_id":"","url":"https://api.github.com/users/ms-jihua","html_url":"https://github.com/ms-jihua","followers_url":"https://api.github.com/users/ms-jihua/followers","following_url":"https://api.github.com/users/ms-jihua/following{/other_user}","gists_url":"https://api.github.com/users/ms-jihua/gists{/gist_id}","starred_url":"https://api.github.com/users/ms-jihua/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ms-jihua/subscriptions","organizations_url":"https://api.github.com/users/ms-jihua/orgs","repos_url":"https://api.github.com/users/ms-jihua/repos","events_url":"https://api.github.com/users/ms-jihua/events{/privacy}","received_events_url":"https://api.github.com/users/ms-jihua/received_events","type":"User","site_admin":false},"repo":{"id":63092436,"name":"WinObjC","full_name":"ms-jihua/WinObjC","owner":{"login":"ms-jihua","id":16024095,"avatar_url":"https://avatars.githubusercontent.com/u/16024095?v=3","gravatar_id":"","url":"https://api.github.com/users/ms-jihua","html_url":"https://github.com/ms-jihua","followers_url":"https://api.github.com/users/ms-jihua/followers","following_url":"https://api.github.com/users/ms-jihua/following{/other_user}","gists_url":"https://api.github.com/users/ms-jihua/gists{/gist_id}","starred_url":"https://api.github.com/users/ms-jihua/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ms-jihua/subscriptions","organizations_url":"https://api.github.com/users/ms-jihua/orgs","repos_url":"https://api.github.com/users/ms-jihua/repos","events_url":"https://api.github.com/users/ms-jihua/events{/privacy}","received_events_url":"https://api.github.com/users/ms-jihua/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ms-jihua/WinObjC","description":"Objective-C for Windows","fork":true,"url":"https://api.github.com/repos/ms-jihua/WinObjC","forks_url":"https://api.github.com/repos/ms-jihua/WinObjC/forks","keys_url":"https://api.github.com/repos/ms-jihua/WinObjC/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ms-jihua/WinObjC/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ms-jihua/WinObjC/teams","hooks_url":"https://api.github.com/repos/ms-jihua/WinObjC/hooks","issue_events_url":"https://api.github.com/repos/ms-jihua/WinObjC/issues/events{/number}","events_url":"https://api.github.com/repos/ms-jihua/WinObjC/events","assignees_url":"https://api.github.com/repos/ms-jihua/WinObjC/assignees{/user}","branches_url":"https://api.github.com/repos/ms-jihua/WinObjC/branches{/branch}","tags_url":"https://api.github.com/repos/ms-jihua/WinObjC/tags","blobs_url":"https://api.github.com/repos/ms-jihua/WinObjC/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ms-jihua/WinObjC/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ms-jihua/WinObjC/git/refs{/sha}","trees_url":"https://api.github.com/repos/ms-jihua/WinObjC/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ms-jihua/WinObjC/statuses/{sha}","languages_url":"https://api.github.com/repos/ms-jihua/WinObjC/languages","stargazers_url":"https://api.github.com/repos/ms-jihua/WinObjC/stargazers","contributors_url":"https://api.github.com/repos/ms-jihua/WinObjC/contributors","subscribers_url":"https://api.github.com/repos/ms-jihua/WinObjC/subscribers","subscription_url":"https://api.github.com/repos/ms-jihua/WinObjC/subscription","commits_url":"https://api.github.com/repos/ms-jihua/WinObjC/commits{/sha}","git_commits_url":"https://api.github.com/repos/ms-jihua/WinObjC/git/commits{/sha}","comments_url":"https://api.github.com/repos/ms-jihua/WinObjC/comments{/number}","issue_comment_url":"https://api.github.com/repos/ms-jihua/WinObjC/issues/comments{/number}","contents_url":"https://api.github.com/repos/ms-jihua/WinObjC/contents/{+path}","compare_url":"https://api.github.com/repos/ms-jihua/WinObjC/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ms-jihua/WinObjC/merges","archive_url":"https://api.github.com/repos/ms-jihua/WinObjC/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ms-jihua/WinObjC/downloads","issues_url":"https://api.github.com/repos/ms-jihua/WinObjC/issues{/number}","pulls_url":"https://api.github.com/repos/ms-jihua/WinObjC/pulls{/number}","milestones_url":"https://api.github.com/repos/ms-jihua/WinObjC/milestones{/number}","notifications_url":"https://api.github.com/repos/ms-jihua/WinObjC/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ms-jihua/WinObjC/labels{/name}","releases_url":"https://api.github.com/repos/ms-jihua/WinObjC/releases{/id}","deployments_url":"https://api.github.com/repos/ms-jihua/WinObjC/deployments","created_at":"2016-07-11T18:32:57Z","updated_at":"2016-07-11T18:33:10Z","pushed_at":"2016-12-02T23:03:26Z","git_url":"git://github.com/ms-jihua/WinObjC.git","ssh_url":"git@github.com:ms-jihua/WinObjC.git","clone_url":"https://github.com/ms-jihua/WinObjC.git","svn_url":"https://github.com/ms-jihua/WinObjC","homepage":"","size":333411,"stargazers_count":0,"watchers_count":0,"language":"Objective-C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"Microsoft:develop","ref":"develop","sha":"56fe72e7e8f80d2c3d27047fe9ce58ecb6bcf6e6","user":{"login":"Microsoft","id":6154722,"avatar_url":"https://avatars.githubusercontent.com/u/6154722?v=3","gravatar_id":"","url":"https://api.github.com/users/Microsoft","html_url":"https://github.com/Microsoft","followers_url":"https://api.github.com/users/Microsoft/followers","following_url":"https://api.github.com/users/Microsoft/following{/other_user}","gists_url":"https://api.github.com/users/Microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/Microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Microsoft/subscriptions","organizations_url":"https://api.github.com/users/Microsoft/orgs","repos_url":"https://api.github.com/users/Microsoft/repos","events_url":"https://api.github.com/users/Microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/Microsoft/received_events","type":"Organization","site_admin":false},"repo":{"id":37950166,"name":"WinObjC","full_name":"Microsoft/WinObjC","owner":{"login":"Microsoft","id":6154722,"avatar_url":"https://avatars.githubusercontent.com/u/6154722?v=3","gravatar_id":"","url":"https://api.github.com/users/Microsoft","html_url":"https://github.com/Microsoft","followers_url":"https://api.github.com/users/Microsoft/followers","following_url":"https://api.github.com/users/Microsoft/following{/other_user}","gists_url":"https://api.github.com/users/Microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/Microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Microsoft/subscriptions","organizations_url":"https://api.github.com/users/Microsoft/orgs","repos_url":"https://api.github.com/users/Microsoft/repos","events_url":"https://api.github.com/users/Microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/Microsoft/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Microsoft/WinObjC","description":"Objective-C for Windows","fork":false,"url":"https://api.github.com/repos/Microsoft/WinObjC","forks_url":"https://api.github.com/repos/Microsoft/WinObjC/forks","keys_url":"https://api.github.com/repos/Microsoft/WinObjC/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Microsoft/WinObjC/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Microsoft/WinObjC/teams","hooks_url":"https://api.github.com/repos/Microsoft/WinObjC/hooks","issue_events_url":"https://api.github.com/repos/Microsoft/WinObjC/issues/events{/number}","events_url":"https://api.github.com/repos/Microsoft/WinObjC/events","assignees_url":"https://api.github.com/repos/Microsoft/WinObjC/assignees{/user}","branches_url":"https://api.github.com/repos/Microsoft/WinObjC/branches{/branch}","tags_url":"https://api.github.com/repos/Microsoft/WinObjC/tags","blobs_url":"https://api.github.com/repos/Microsoft/WinObjC/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Microsoft/WinObjC/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Microsoft/WinObjC/git/refs{/sha}","trees_url":"https://api.github.com/repos/Microsoft/WinObjC/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Microsoft/WinObjC/statuses/{sha}","languages_url":"https://api.github.com/repos/Microsoft/WinObjC/languages","stargazers_url":"https://api.github.com/repos/Microsoft/WinObjC/stargazers","contributors_url":"https://api.github.com/repos/Microsoft/WinObjC/contributors","subscribers_url":"https://api.github.com/repos/Microsoft/WinObjC/subscribers","subscription_url":"https://api.github.com/repos/Microsoft/WinObjC/subscription","commits_url":"https://api.github.com/repos/Microsoft/WinObjC/commits{/sha}","git_commits_url":"https://api.github.com/repos/Microsoft/WinObjC/git/commits{/sha}","comments_url":"https://api.github.com/repos/Microsoft/WinObjC/comments{/number}","issue_comment_url":"https://api.github.com/repos/Microsoft/WinObjC/issues/comments{/number}","contents_url":"https://api.github.com/repos/Microsoft/WinObjC/contents/{+path}","compare_url":"https://api.github.com/repos/Microsoft/WinObjC/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Microsoft/WinObjC/merges","archive_url":"https://api.github.com/repos/Microsoft/WinObjC/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Microsoft/WinObjC/downloads","issues_url":"https://api.github.com/repos/Microsoft/WinObjC/issues{/number}","pulls_url":"https://api.github.com/repos/Microsoft/WinObjC/pulls{/number}","milestones_url":"https://api.github.com/repos/Microsoft/WinObjC/milestones{/number}","notifications_url":"https://api.github.com/repos/Microsoft/WinObjC/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Microsoft/WinObjC/labels{/name}","releases_url":"https://api.github.com/repos/Microsoft/WinObjC/releases{/id}","deployments_url":"https://api.github.com/repos/Microsoft/WinObjC/deployments","created_at":"2015-06-23T23:14:58Z","updated_at":"2016-12-02T15:36:49Z","pushed_at":"2016-12-02T23:04:37Z","git_url":"git://github.com/Microsoft/WinObjC.git","ssh_url":"git@github.com:Microsoft/WinObjC.git","clone_url":"https://github.com/Microsoft/WinObjC.git","svn_url":"https://github.com/Microsoft/WinObjC","homepage":"","size":368742,"stargazers_count":5536,"watchers_count":5536,"language":"Objective-C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":731,"mirror_url":null,"open_issues_count":291,"forks":731,"open_issues":291,"watchers":5536,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/Microsoft/WinObjC/pulls/1504"},"html":{"href":"https://github.com/Microsoft/WinObjC/pull/1504"},"issue":{"href":"https://api.github.com/repos/Microsoft/WinObjC/issues/1504"},"comments":{"href":"https://api.github.com/repos/Microsoft/WinObjC/issues/1504/comments"},"review_comments":{"href":"https://api.github.com/repos/Microsoft/WinObjC/pulls/1504/comments"},"review_comment":{"href":"https://api.github.com/repos/Microsoft/WinObjC/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Microsoft/WinObjC/pulls/1504/commits"},"statuses":{"href":"https://api.github.com/repos/Microsoft/WinObjC/statuses/4fad65482028cad182459816aceab43dcd4ab981"}}}}
{"actor":{"display_login":"msft-Jeyaram"}}